Files
notarius/docs/roadmap/implementation.md

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], prefix npc: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, prefix location:sha256:; and
  • item: dnd.item_registry.identity.v1, SHA-256 of compact JSON [policy, comparison_name], prefix item: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, and docs/policy/testing.md before 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.go as 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/dnd and assets/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

  1. In internal/modules/dnd/types.go, replace NPCListKind and NPCList with NPCRegistryKind and NPCRegistry. Retain NPC with required ID, Name, and SourceRefs, and retain the durable root field npcs.
  2. Update every typed consumer, merger, evidence projection, validator, normalizer, extractor, test fixture, integration helper, and registry registration to use dnd.NPCRegistry and dnd.NPCRegistryKind. Do not leave a Go alias for the retired names.
  3. In the existing NPC codec package, replace the durable schema with dnd_npc_registry.v1.json, schema ID notarius.dnd.npc_registry, schema name notarius_dnd_npc_registry_v1, and version v1. Keep the strict npcs envelope and application/json media type.
  4. 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.
  5. 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.
  6. Update the current docs/integrations/dnd-npc-artifacts.md in place so its artifact kind, schema identity, Go-independent ID algorithm, and wire example match this stage. It must continue to name dnd/npcs as the current producer until Stage 2.

Acceptance criteria

  • No production Go code refers to NPCList or NPCListKind.
  • The registered codec round-trips the strict NPCRegistry v1 contract and reports the target kind and schema identity.
  • All current NPC-grounded consumers compile against NPCRegistry without changing their reference-slot names yet.
  • There is no compatibility alias or decoder for dnd/npc-list or notarius.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

  1. Move the stage packages to Go-compatible canonical paths: codec/npcregistry, extract/npcregistry, normalize/npcregistry, and validate/npcregistry/.... Domain helpers under internal/modules/dnd/npcs may remain because they own NPC identity rather than a selectable module.
  2. 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 to dnd.npc_registry.
  3. Move assets/dnd/npcs/{extract,normalize} to assets/dnd/npc-registry/{extract,normalize}. Use prompt IDs dnd.npc_registry and dnd.npc_registry.normalize; use private schema ID notarius.dnd.npc_registry.llm, schema name notarius_dnd_npc_registry_llm_v1, and filename dnd_npc_registry_llm.v1.json.
  4. Rename common-dnd-npcs.md to common-dnd-npc-registry.md. Change the rendered PromptKit input and every module-facing reference slot from npcs to npc_registry in 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.
  5. 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.
  6. 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_registry input without duplicating its ordering assertions in module-local tests.
  7. 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.
  8. 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 type NPC, and domain helper package name npcs are not legacy module identifiers and should remain.

Acceptance criteria

  • dnd/npc-registry is the only selectable NPC registry extract/normalize key.
  • All NPC-registry consumers expose npc_registry and accept only dnd/npc-registry artifacts.
  • Prompt and schema assets load only from assets/dnd/npc-registry and retain the documented cache order.
  • Current docs and examples contain no claim that dnd/npcs is 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

  1. Replace NPCInteractionListKind, NPCInteractionList, NPCInteractionKind, and NPCInteraction with NPCOccurrenceListKind, NPCOccurrenceList, NPCOccurrenceKind, and NPCOccurrence. The envelope field is occurrences; each record has required npc_id, name, kind, and source_refs.
  2. 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.
  3. In the current codec package, adopt dnd/npc-occurrence-list, durable schema ID notarius.dnd.npc_occurrences, schema name notarius_dnd_npc_occurrences_v1, and strict file dnd_npc_occurrences.v1.json.
  4. Change the current NPC-interaction private response contract to require npc_id as well as name, kind, and source_refs. Use private schema ID notarius.dnd.npc_occurrences.llm, schema name notarius_dnd_npc_occurrences_llm_v1, and a renamed schema file even though the prompt ID moves in Stage 4.
  5. 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.
  6. 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.
  7. Update enemy-event grounding to consume NPCOccurrenceList, filtering combat_opponent occurrences while carrying only source-free grounding values. Do not add NPC IDs to the enemy-event durable contract.
  8. Update docs/integrations/dnd-npc-interaction-artifacts.md in 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 occurrences and 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

  1. Move the codec, extract, normalize, validate, and D&D helper packages from npcinteractions to npcoccurrences where they own the occurrence artifact.
  2. Set extract and normalize keys to dnd/npc-occurrences; rename validator keys and the provided capability to the npc-occurrences/ dnd.npc_occurrences vocabulary.
  3. Move assets/dnd/npc-interactions to assets/dnd/npc-occurrences. Change the extraction prompt ID to dnd.npc_occurrences, update instructions from “interactions” to “occurrences” without changing category semantics, and keep the target private schema identity established in Stage 3.
  4. Rename the generated reference and PromptKit grounding input consumed by enemy events from npc_interactions to npc_occurrences. Update combat grounding assets, reference specs, fingerprint metadata, checkpoint inputs, and tests consistently.
  5. Update central registration, default validator chains, artifact evidence and merge registration, prompt-cache tests, configuration keys, examples, and current documentation.
  6. Rename the integration contract to docs/integrations/dnd-npc-occurrence-artifacts.md and update every link from NPC registry, enemy event, combat, internal D&D, configuration, and JSON output documentation.
  7. Delete every old package, key, schema, prompt, capability, asset, and current- behavior reference for dnd/npc-interactions and npc_interactions. Do not retain a module alias.

Acceptance criteria

  • dnd/npc-occurrences is the only selectable NPC occurrence key.
  • Enemy events require npc_occurrences of kind dnd/npc-occurrence-list.
  • Current catalogs, examples, and documentation use occurrence vocabulary.
  • No production package or asset directory named npcinteractions or npc-interactions 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 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

  1. Replace LocationListKind and LocationList with LocationRegistryKind and LocationRegistry. Retain Location and the durable locations root.
  2. Update all typed location-registry consumers, especially location-occurrence extraction, normalization, validation, reference resolution, merge, evidence, registration, and tests. Do not leave aliases.
  3. In the current location codec package, use kind dnd/location-registry, schema ID notarius.dnd.location_registry, schema name notarius_dnd_location_registry_v1, and strict file dnd_location_registry.v1.json.
  4. Change the identity policy to dnd.location_registry.identity.v1 and 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.
  5. 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.
  6. Update docs/integrations/dnd-location-artifacts.md in place for the target kind, schema, and identity policy while retaining dnd/locations as the current module key until Stage 6.

Acceptance criteria

  • No production Go code refers to LocationList or LocationListKind.
  • 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

  1. Move the stage packages to codec/locationregistry, extract/locationregistry, normalize/locationregistry, and validate/locationregistry/.... Entity identity and immutable registry helpers may remain under internal/modules/dnd/locations.
  2. Set extract and normalize keys to dnd/location-registry; rename validator keys and the provided capability to dnd.location_registry.
  3. Move assets/dnd/locations/{extract,normalize} to assets/dnd/location-registry/{extract,normalize}. Use prompt IDs dnd.location_registry and dnd.location_registry.normalize; use private schema ID notarius.dnd.location_registry.llm, schema name notarius_dnd_location_registry_llm_v1, and filename dnd_location_registry_llm.v1.json.
  4. 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, and upstairs. Do not use capitalization as the eligibility test and do not add a brittle deterministic word blacklist.
  5. Rename the required location-occurrence reference slot and PromptKit input from locations to location_registry. Preserve the ordered source-free {id, name} projection and exact ID/name validation at extraction and normalization.
  6. 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.
  7. Update central registration, prompt composition, validator chains, configuration, examples, and current docs. Rename the integration contract to docs/integrations/dnd-location-registry-artifacts.md and update links.
  8. Remove old module/package/asset/prompt/validator/capability identities and old reference-slot names. The durable locations field and domain helper package remain valid.

Acceptance criteria

  • dnd/location-registry is 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_registry of kind dnd/location-registry at extract and normalize stages.
  • No production compatibility alias for dnd/locations 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 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

  1. Add ItemRegistryKind, ItemRegistry, and Item to the D&D domain types. The strict envelope is {"items":[...]}; each item has required id, name, and source_refs.
  2. Add an item identity package under internal/modules/dnd/items/identity. Implement comparison normalization consistent with the NPC identity text family, policy dnd.item_registry.identity.v1, compact JSON [policy, comparison_name], prefix item:sha256:, syntax checks, registry uniqueness validation, and deterministic errors.
  3. 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.
  4. Add internal/modules/dnd/codec/itemregistry with strict durable schema dnd_item_registry.v1.json, ID notarius.dnd.item_registry, name notarius_dnd_item_registry_v1, version v1, and media type application/json.
  5. 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.
  6. 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

  1. Add internal/modules/dnd/extract/itemregistry with key dnd/item-registry, artifact kind dnd/item-registry, LLM-backed execution, the ordinary campaign reference slots, and prompt ID dnd.item_registry.
  2. Add assets/dnd/item-registry/extract containing prompt.yaml, one coherent instructions.md, and strict private schema dnd_item_registry_llm.v1.json with ID notarius.dnd.item_registry.llm and name notarius_dnd_item_registry_llm_v1. The private response contains required item name and source_refs; deterministic code supplies source identity and derives the durable item ID.
  3. 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.
  4. 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.
  5. 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.
  6. Add validate/itemregistry/shape, source_refs, and source_relatedness packages and keys using the final module vocabulary. Keep relatedness advisory according to existing D&D conventions.
  7. 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.
  8. 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

  1. Add internal/modules/dnd/normalize/itemregistry with key dnd/item-registry, LLM-backed execution, prompt ID dnd.item_registry.normalize, and the same retry/fallback contract used by NPC and location registry normalization.
  2. 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.
  3. Add assets/dnd/item-registry/normalize with prompt.yaml, instructions.md, and candidates.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.
  4. Explicitly prevent reconciliation across currency denominations, materially different item types, or merely nearby objects. Do not create per-instance identities or infer properties.
  5. Add validate/itemregistry/identity and its default normalize-chain position. Test retry, invalid structured output, operational error, warning bounds, idempotence, order, non-mutation, and content-safe diagnostics.
  6. 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.
  7. 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-registry is 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

  1. Replace ItemEventListKind, ItemEventList, ItemEventKind, and ItemEvent with ItemOccurrenceListKind, ItemOccurrenceList, ItemOccurrenceKind, and ItemOccurrence. Use durable root occurrences; each record has required item_id, name, kind, and source_refs, plus conditional quantity, from, and to.
  2. 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.
  3. In the current codec package, adopt kind dnd/item-occurrence-list, schema ID notarius.dnd.item_occurrences, schema name notarius_dnd_item_occurrences_v1, and strict file dnd_item_occurrences.v1.json.
  4. Change the private response schema to notarius.dnd.item_occurrences.llm/ notarius_dnd_item_occurrences_llm_v1 in dnd_item_occurrences_llm.v1.json. Require every property. Represent absent quantity, from, and to as nullable private fields and map them to the durable conditional fields without fabricating values.
  5. Add required item_registry reference slots to both extraction and normalization, accepting only dnd/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.
  6. 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.
  7. 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_id and the new envelope.
  8. Update the maintained complete example immediately: produce dnd/item-registry in the earlier registry step and bind its generated artifact as item_registry to the still-current dnd/item-events extract and normalize stages. Keep the example valid at the end of this stage.
  9. Update docs/integrations/dnd-item-event-artifacts.md in 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

  1. Move internal/modules/dnd/itemevents to itemoccurrences and move codec, extract, normalize, and validate packages to the corresponding itemoccurrences paths.
  2. Set extract and normalize keys to dnd/item-occurrences; rename validator keys and the provided capability to dnd.item_occurrences.
  3. Move assets/dnd/item-events to assets/dnd/item-occurrences. Use prompt ID dnd.item_occurrences, the target private schema identity from Stage 10, and occurrence terminology throughout module instructions.
  4. Update all imports, central registrations, default chains, metadata, fingerprints, prompt composition cases, configuration keys, example lanes, generated references, output expectations, and tests.
  5. Rename the integration contract to docs/integrations/dnd-item-occurrence-artifacts.md and update links from item registry, configuration, internal D&D, and JSON output documentation.
  6. 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-occurrences is the only selectable item occurrence key.
  • All item occurrence packages, prompts, validators, schemas, and docs use the canonical vocabulary.
  • The complete example binds item_registry into 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

  1. Finalize examples/dnd-complete.config.yml with an earlier registry step containing npc-registry, location-registry, and item-registry lanes alongside scene descriptions. The next step contains NPC, location, and item occurrences plus spell and combat lanes. The derived enemy step consumes npc_registry, npc_occurrences, combat turns, and scene descriptions.
  2. Use generated-reference aliases npc_registry, location_registry, item_registry, and npc_occurrences. Preserve explicit step-and-lane selectors and stage-local spell-catalog bindings. Do not infer dependencies from matching names.
  3. Update scene-plan eligibility configuration for all renamed lane labels while preserving the shared chunk plan and exact combat-scene routing semantics.
  4. 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.
  5. 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.
  6. 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.
  7. 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

  1. Update docs/config.md as the canonical owner of selectable module keys, validator keys, default chains, reference slots, requiredness, size limits, execution classes, profile behavior, and ordered binding examples.
  2. Update docs/internal/dnd.md for 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.
  3. 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.
  4. 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, and dnd-item-occurrence-artifacts.md.
  5. 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.
  6. Verify that only examples/dnd-minimal.config.yml and examples/dnd-complete.config.yml remain as maintained D&D configurations, that both are secret-free, and that documentation links to rather than reproduces them.
  7. 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

  1. 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. Exclude docs/roadmap/, where migration context intentionally names the old values.
  2. Search for retired Go artifact identifiers NPCList, NPCInteraction, LocationList, and ItemEvent. Distinguish legitimate words or unrelated concepts from compatibility remnants; remove every actual old contract or alias.
  3. Verify the final package and asset trees contain only canonical registry and occurrence stage packages. Confirm every D&D prompt subtree has prompt.yaml and instructions.md, manifests select only existing assets, and all prompt/schema fingerprints are content-safe.
  4. Verify every private D&D response schema has additionalProperties: false, includes every declared property in required, and uses the exact final private identity. Verify durable schemas independently through their codecs; do not conflate private and durable contracts.
  5. 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.
  6. 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.
  7. 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.
  8. 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.md is 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