Audit NPC item and location occurrences

This commit is contained in:
2026-08-08 22:30:23 +00:00
parent 551e4daea2
commit 5d6305f21a

View File

@@ -20,10 +20,10 @@ change only roadmap audit documents do not change that production target.
Pending final synthesis. The initial baseline is healthy. The architecture,
configuration/CLI, pipeline composition, reference/handoff, runtime, state,
LLM, generic/Seriatim, shared D&D, and registry-family reviews have found three
High findings, four Medium findings, and twenty Low findings, with no
production dependency
inversion, unbounded framework worker pool, completion-order-dependent result
LLM, generic/Seriatim, shared D&D, registry-family, and occurrence-family
reviews have found three High findings, five Medium findings, and twenty-two
Low findings, with no production dependency inversion, unbounded framework
worker pool, completion-order-dependent result
assembly, debug-to-cache coupling, model-visible credential material in the
embedded LLM assets, or domain leakage across the Seriatim and generic module
boundaries.
@@ -57,10 +57,13 @@ Final cross-area ordering is pending synthesis.
| MOD-002 | Low | Efficiency | Reuse compiled response schemas within a prepared validator |
| MOD-003 | Low | Simplicity | Remove unreachable JSON metadata clone helpers |
| DND-CORE-001 | Low | Simplicity | Remove the unused lossy unit-reference constructor |
| DND-REG-001 | Low | Correctness | Reject reversed evidence ranges at the registry codec boundary |
| DND-REG-001 | Low | Correctness | Reject reversed evidence ranges at durable D&D codec boundaries |
| DND-REG-002 | Low | Correctness | Keep NPC extraction evidence inside the current chunk |
| DND-REG-003 | Low | Efficiency | Index item and location duplicate groups |
| DND-REG-004 | Low | Efficiency | Select location identity anchors without sorting |
| DND-OCC-001 | Medium | Correctness | Align item occurrence evidence fields with the shared prompt |
| DND-OCC-002 | Low | Simplicity | Remove unused campaign references from NPC occurrence normalization |
| DND-OCC-003 | Low | Efficiency | Reuse canonical item occurrence evidence |
## Findings
@@ -856,46 +859,56 @@ Final cross-area ordering is pending synthesis.
### NPC, Item, And Location Registries
### DND-REG-001 — Reject reversed evidence ranges at the registry codec boundary
### DND-REG-001 — Reject reversed evidence ranges at durable D&D codec boundaries
- **Severity:** Low
- **Category:** Correctness
- **Evidence:** All three registry integration contracts require that a source
range's start not follow its end
- **Evidence:** The three registry and three occurrence integration contracts
require that a source range's start not follow its end
(`docs/integrations/dnd-npc-registry-artifacts.md:32``34`,
`dnd-item-registry-artifacts.md:33``35`, and
`dnd-location-registry-artifacts.md:34``36`). The three durable codec
`dnd-location-registry-artifacts.md:34``36`; and
`dnd-npc-occurrence-artifacts.md:33``36`,
`dnd-item-occurrence-artifacts.md:41``43`, and
`dnd-location-occurrence-artifacts.md:33``35`). All six durable codec
validators check only that both endpoints are positive
(`internal/modules/dnd/codec/npcregistry/codec.go:96``106`,
`codec/itemregistry/codec.go:97``107`, and
`codec/locationregistry/codec.go:97``107`). Direct registry references are
`codec/locationregistry/codec.go:97``107`; and
`codec/npcoccurrences/codec.go:99``109`,
`codec/itemoccurrences/codec.go:117``127`, and
`codec/locationoccurrences/codec.go:100``110`). Direct registry references are
decoded and identity-checked by `npcs/registry.loadRegistry`,
`items/registry.loadRegistry`, and `locations/registry.loadRegistry`, but do
not pass through the generated-output source-reference validators. A durable
artifact with `{start_unit_id: 2, end_unit_id: 1}` and otherwise valid
identity is therefore accepted; for locations, `validIdentityReference` at
registry or occurrence artifact with
`{start_unit_id: 2, end_unit_id: 1}` and otherwise valid fields is therefore
accepted; for locations, `validIdentityReference` at
`internal/modules/dnd/locations/identity/identity.go:170``171` also treats
that reversed range as a valid identity anchor.
- **Impact:** An externally supplied registry can be accepted as approved even
though its evidence cannot denote the documented forward source interval.
- **Impact:** An externally supplied registry or occurrence list can be
accepted as approved even though its evidence cannot denote the documented
forward source interval.
NPC and item prompt projections then hide the malformed provenance, while a
location can derive and retain a durable ID from it; only later consumers
that happen to construct contextual grounding against the same source may
reject it. Generated pipeline outputs remain protected by their source-
reference validator chains, which limits current exposure.
- **Recommendation:** Add the order-independent structural condition
`start_unit_id <= end_unit_id` to each registry codec's durable validation,
and make location identity reject reversed anchors as a defense in depth.
`start_unit_id <= end_unit_id` to all six reviewed codecs' durable
validation, and make location identity reject reversed anchors as a defense
in depth.
Keep document membership and current-chunk coverage in the existing
validators, where the source document is available.
- **Preserve:** Retain positive exact source-unit identifiers, strict unknown-
field/trailing-value rejection, location identity's earliest canonical
anchor policy, and the separation between source-independent durable shape
validation and source-dependent evidence validation.
- **Validation:** Add codec encode/decode cases for reversed ranges in all three
registry families, a location identity case that refuses a reversed-only
anchor, and direct registry resolver cases proving malformed referenced JSON
is rejected; run the three codec, identity, and registry package suites.
- **Validation:** Add codec encode/decode cases for reversed ranges in all six
reviewed families, a location identity case that refuses a reversed-only
anchor, and direct registry and occurrence reference cases proving malformed
referenced JSON is rejected; run the codec, identity, registry, occurrence,
and assembled CLI suites.
- **Grouping:** Independent.
### DND-REG-002 — Keep NPC extraction evidence inside the current chunk
@@ -995,6 +1008,111 @@ Final cross-area ordering is pending synthesis.
run the location identity, registry, and normalizer tests.
- **Grouping:** Independent.
### NPC, Item, And Location Occurrences
### DND-OCC-001 — Align item occurrence evidence fields with the shared prompt
- **Severity:** Medium
- **Category:** Correctness
- **Evidence:** The shared model-visible evidence instruction tells every D&D
extractor to return integer `start_unit_id` and `end_unit_id` fields
(`assets/dnd/shared/prompts/common-dnd-extraction-evidence.md:1``4`). NPC and
location occurrence extraction follow that convention, but the item
occurrence private response DTO instead requires `start_segment` and
`end_segment`
(`internal/modules/dnd/extract/itemoccurrences/model.go:16``18`), and its
strict structured-output schema requires the same incompatible names
(`assets/dnd/item-occurrences/schemas/dnd_item_occurrences_llm.v1.json:20``29`).
The representative generated pipeline fixture must likewise emit the
segment-named fields to pass
(`internal/cli/dnd_enemy_events_contract_test.go:318``334`).
- **Impact:** The prompt and enforced response schema give the model
contradictory instructions at one structured-output boundary. A model that
follows the shared evidence instruction produces missing required fields and
disallowed unknown fields, causing an otherwise valid item occurrence
candidate to be rejected and retried. Provider-side schema steering may
conceal the mismatch for some models, but cannot make the prompt contract
coherent.
- **Recommendation:** Rename the item occurrence private response fields and
schema properties to `start_unit_id` and `end_unit_id`, update the adapter
and fixtures, and verify that the affected response-schema fingerprint
changes. Add an assembled-prompt contract proving every evidence field named
by the item response schema matches the shared instruction.
- **Preserve:** Keep source IDs out of model output, inject the current source
identity locally, retain exact positive transcript unit IDs, strict
structured decoding, current-chunk evidence validation, and the unchanged
durable occurrence wire shape.
- **Validation:** Retain item extractor malformed-response and citation tests,
update the generated multi-family CLI fixture to use unit-named endpoints,
add the prompt/schema alignment assertion, and run the item occurrence and
CLI suites.
- **Grouping:** Independent.
### DND-OCC-002 — Remove unused campaign references from NPC occurrence normalization
- **Severity:** Low
- **Category:** Simplicity
- **Evidence:** NPC occurrence normalization declares the optional campaign
`glossary`, `party`, `players`, and deprecated `roster` slots as material used
for occurrence disambiguation
(`internal/modules/dnd/normalize/npcoccurrences/normalizer.go:38``43`) and
includes them beside the required registry in `ReferenceSlots` (lines
252263). Construction retains only an NPC registry resolver (lines 5167),
and normalization resolves and uses only that registry plus the source
document (lines 99123). Item and location occurrence normalizers expose
only their required family registry.
- **Impact:** Bindings that cannot affect NPC normalization are nevertheless
admitted into resolved profiles, materialized, recorded in manifests and
dependency identities, and can invalidate checkpoints when their content
changes. The descriptions also imply a disambiguation behavior the
deterministic normalizer does not implement.
- **Recommendation:** Remove the four campaign slots and their descriptions
from the NPC occurrence normalizer, leaving only required `npc_registry`.
Keep campaign context on extraction, where it is model-visible and can
actually influence selection.
- **Preserve:** Retain exact registry ID/name validation and canonicalization,
operation-time registry overrides, source-reference ordering, exact duplicate
collapse, bounded warnings, and all extraction reference slots.
- **Validation:** Update module-spec, reference-binding, manifest, and
checkpoint dependency tests to require exactly the registry slot during
normalization; prove extraction still accepts campaign context; run NPC
occurrence and assembled CLI tests.
- **Grouping:** Independent.
### DND-OCC-003 — Reuse canonical item occurrence evidence
- **Severity:** Low
- **Category:** Efficiency
- **Evidence:** Item normalization canonicalizes each occurrence's evidence
once in `normalizeOccurrence`
(`internal/modules/dnd/normalize/itemoccurrences/normalizer.go:174``195`),
then sorts those records through `itemoccurrences.Less` (lines 155157) and
builds duplicate keys through `ExactIdentity` (lines 220229). `Less`
canonicalizes both reference slices again at its final tie-breaker
(`internal/modules/dnd/itemoccurrences/itemoccurrences.go:95``125`), while
`ExactIdentity` canonicalizes each slice again at lines 145163. The
invariants validator first verifies canonical order and uniqueness, then
calls both helpers again
(`internal/modules/dnd/validate/itemoccurrences/invariants/validator.go:65``95`).
- **Impact:** Tie-heavy merged lists repeatedly allocate, sort, and deduplicate
evidence that the normalizer has already canonicalized; normalized artifact
validation repeats the same work. Transcript and LLM costs dominate ordinary
runs, so this is a localized low-severity deterministic cost.
- **Recommendation:** Add canonical-input comparator and identity-key paths, or
precompute canonical sort/dedup keys per normalized record, and use them only
after the caller has established canonical evidence. Retain the current
defensive public helpers for arbitrary or malformed candidates that still
need literal-fallback ordering.
- **Preserve:** Keep exact canonical ordering, nil and invalid-reference
diagnostic behavior, holder and quantity distinctions, collision-safe
identity keys, stable input provenance for warnings, and non-mutating helper
contracts.
- **Validation:** Compare optimized normalization and invariant results against
the existing permuted/duplicate/invalid evidence fixtures; add a tie-heavy
benchmark or canonicalization-count hook showing one evidence canonicalization
per normalized record; run item occurrence normalize/validator tests.
- **Grouping:** Independent.
<!--
Finding template for later audit stages:
@@ -1031,13 +1149,13 @@ evidence projector.
| Spells | `dnd/spell-list` / `dnd.SpellList` | `dnd/spells` (LLM) → typed `appendorder` (deterministic) → `dnd/spells` (deterministic) | `B + catalog` / `B + catalog` | `C` plus optional `spell_catalog` and `npc_registry` / optional `spell_catalog` | `codec/spells`; extractor owns its prompt and private response schema; normalizer has no prompt | Catalog overlay and NPC caster grounding are optional and never evidence; confirm spell/catalog and scene-family behavior in the spells/scenes review. |
| NPC registry | `dnd/npc-registry` / `dnd.NPCRegistry` | `dnd/npc-registry` (LLM) → typed `appendorder` (deterministic) → `dnd/npc-registry` (LLM) | `B` / `B + identity` | `C` / none | `codec/npcregistry`; extractor and normalizer own prompts; extractor owns its response schema, while normalize uses the shared private entity-reconciliation schema | Confirmed: normalized comparison-name identity, deterministic exact duplicate consolidation, proposal-only semantic groups, collision-safe application, retry/fallback, and immutable name/identity projections; DND-REG-001 and DND-REG-002 record evidence-boundary gaps. |
| Combat turns | `dnd/combat-turn-list` / `dnd.CombatTurnList` | `dnd/combat-turns` (LLM) → typed `appendorder` (deterministic) → `dnd/combat-turns` (deterministic) | `B` / `B + invariants` | `C`, optional `npc_registry`, required `scene_descriptions` / optional `npc_registry` | `codec/combatturns`; extractor owns its prompt and private response schema; normalizer has no prompt | Scene descriptions gate LLM execution and NPC grounding is not evidence; confirm gate and empty-result semantics in the combat/enemy review. |
| Item occurrences | `dnd/item-occurrence-list` / `dnd.ItemOccurrenceList` | `dnd/item-occurrences` (LLM) → typed `appendorder` (deterministic) → `dnd/item-occurrences` (deterministic) | `B + registry` / `B + registry + invariants` | `C` plus required `item_registry` / required `item_registry` | `codec/itemoccurrences`; extractor owns its prompt and private response schema; normalizer has no prompt | Registry identity grounds current-transcript facts but never supplies evidence; confirm quantities, holders, and registry projection in the occurrence review. |
| Item occurrences | `dnd/item-occurrence-list` / `dnd.ItemOccurrenceList` | `dnd/item-occurrences` (LLM) → typed `appendorder` (deterministic) → `dnd/item-occurrences` (deterministic) | `B + registry` / `B + registry + invariants` | `C` plus required `item_registry` / required `item_registry` | `codec/itemoccurrences`; extractor owns its prompt and private response schema; normalizer has no prompt | Confirmed: exact names-only registry resolution is all-or-nothing, registry provenance never becomes evidence, and quantity/holder rules survive canonical ordering and duplicate collapse. DND-REG-001, DND-OCC-001, and DND-OCC-003 record bounded codec, prompt/schema, and repeated-work gaps. |
| Item registry | `dnd/item-registry` / `dnd.ItemRegistry` | `dnd/item-registry` (LLM) → typed `appendorder` (deterministic) → `dnd/item-registry` (LLM) | `B` / `B + identity` | `C` / none | `codec/itemregistry`; extractor and normalizer own prompts; extractor owns its response schema, while normalize uses the shared private entity-reconciliation schema | Confirmed: name identity, exact duplicate evidence union, proposal-only aliases, collision safety, and denomination/type-preserving currency gate; DND-REG-001 and DND-REG-003 record boundary/grouping gaps. |
| NPC occurrences | `dnd/npc-occurrence-list` / `dnd.NPCOccurrenceList` | `dnd/npc-occurrences` (LLM) → typed `appendorder` (deterministic) → `dnd/npc-occurrences` (deterministic) | `B + registry` / `B + registry + invariants` | `C` plus required `npc_registry` / `C` plus required `npc_registry` | `codec/npcoccurrences`; extractor owns its prompt and private response schema; normalizer has no prompt | Registry provenance cannot become occurrence evidence and `mentioned` remains a factual category; confirm category/identity handling in the occurrence review. |
| NPC occurrences | `dnd/npc-occurrence-list` / `dnd.NPCOccurrenceList` | `dnd/npc-occurrences` (LLM) → typed `appendorder` (deterministic) → `dnd/npc-occurrences` (deterministic) | `B + registry` / `B + registry + invariants` | `C` plus required `npc_registry` / `C` plus required `npc_registry` | `codec/npcoccurrences`; extractor owns its prompt and private response schema; normalizer has no prompt | Confirmed: names-only selection resolves to exact registry pairs, registry provenance cannot become occurrence evidence, `mentioned` remains factual, and current-source evidence is canonicalized before exact duplicate collapse. DND-REG-001 and DND-OCC-002 record the codec and unused-normalizer-reference gaps. |
| Scene descriptions | `dnd/scene-description-list` / `dnd.SceneDescriptionList` | `dnd/scene-descriptions` (LLM) → typed `appendorder` (deterministic) → `dnd/scene-descriptions` (deterministic) | `B` / `B + invariants` | optional `glossary`, `party`, and `players` / none | `codec/scenedescriptions`; extractor owns its prompt and private response schema; normalizer has no prompt | Each record has one `source_ref` rather than a slice; the separate `dnd/scenes` LLM chunker owns the full-transcript scene prompt. Confirm scene IDs, ordering, and classification in the spells/scenes review. |
| Enemy events | `dnd/enemy-event-list` / `dnd.EnemyEventList` | `dnd/enemy-events` (LLM) → typed `appendorder` (deterministic) → `dnd/enemy-events` (deterministic) | `B + engagements` / `B + invariants` | `C` plus required `npc_registry`, `scene_descriptions`, `combat_turns`, and `npc_occurrences` / required `npc_registry` | `codec/enemyevents`; extractor owns its prompt and private response schema; normalizer has no prompt | Four generated artifacts ground extraction without becoming event evidence; durable decode separately proves required JSON-field presence. Confirm combat gating, engagement uniqueness, and observation ordering in the combat/enemy review. |
| Location registry | `dnd/location-registry` / `dnd.LocationRegistry` | `dnd/location-registry` (LLM) → typed `appendorder` (deterministic) → `dnd/location-registry` (LLM) | `B` / `B + identity` | `C` / none | `codec/locationregistry`; extractor and normalizer own prompts; extractor owns its response schema, while normalize uses the shared private entity-reconciliation schema | Confirmed: comparison name plus earliest canonical evidence identity, same-name/different-anchor preservation, proposal-only aliases, and immutable context-qualified selectors without durable IDs; DND-REG-001, DND-REG-003, and DND-REG-004 record bounded gaps. |
| Location occurrences | `dnd/location-occurrence-list` / `dnd.LocationOccurrenceList` | `dnd/location-occurrences` (LLM) → typed `appendorder` (deterministic) → `dnd/location-occurrences` (deterministic) | `B + registry` / `B + registry + invariants` | `C` plus required `location_registry` / required `location_registry` | `codec/locationoccurrences`; extractor owns its prompt and private response schema; normalizer has no prompt | Registry grounding cannot become evidence and speculation remains distinct from unsupported inference; confirm category and identity handling in the occurrence review. |
| Location occurrences | `dnd/location-occurrence-list` / `dnd.LocationOccurrenceList` | `dnd/location-occurrences` (LLM) → typed `appendorder` (deterministic) → `dnd/location-occurrences` (deterministic) | `B + registry` / `B + registry + invariants` | `C` plus required `location_registry` / required `location_registry` | `codec/locationoccurrences`; extractor owns its prompt and private response schema; normalizer has no prompt | Confirmed: source-free contextual selectors disambiguate same-name locations without exposing durable IDs, unresolved selections reject the whole response, registry evidence remains separate, and explicit kind precedence preserves speculation/mention distinctions. DND-REG-001 records the codec gap. |
Shared convention review classified the codec surface as safe typed adapters,
not a missing artifact-codec framework. `candidatejson` is the natural owner for
@@ -1078,9 +1196,9 @@ cache identity, and semantic identity while retaining owned loaded values. The
entity-reconciliation helper keeps durable IDs out of prompts, rejects invalid
or colliding selectors and overlapping groups, bounds transcript context, and
returns owned safe groups. Shared comparison policy is versioned, and shared
diagnostics bound displayed issues and warning counts. The registry review now
confirms the three noun-family identity and merge decisions; occurrence
categories and eligibility, scene/spell policy, and combat/enemy behavior remain
diagnostics bound displayed issues and warning counts. The registry and
occurrence reviews now confirm the noun-family identity, projection, category,
and merge decisions; scene/spell policy and combat/enemy behavior remain
assigned to their subsequent reviews.
Finally, repeated `ManifestMetadata` and `CheckpointFingerprints` methods remain
@@ -1776,14 +1894,15 @@ mechanics that recur without erasing those distinctions.
helpers already consolidate prompt assets, candidate JSON, reference slots,
comparison, diagnostics, resolution, and reconciliation. No additional
callback- or reflection-driven helper reduced demonstrated drift.
- **Deferred lane questions:** Registry identity, reconciliation, and immutable
projection policy is now confirmed, with DND-REG-001 through DND-REG-004
recording the bounded gaps. Occurrence categories and registry projections
remain assigned to the occurrence review; spell catalog, scene chunking,
scene IDs, and scene classification to the spells/scenes review; and combat
- **Deferred lane questions:** Registry identity, reconciliation, immutable
projections, and occurrence-category/grounding policy are now confirmed,
with DND-REG-001 through DND-REG-004 and DND-OCC-001 through DND-OCC-003
recording the bounded gaps. Spell catalog, scene chunking, scene IDs, and
scene classification remain assigned to the spells/scenes review; combat
gates, engagement uniqueness, collective labels, and enemy observation
ordering to the combat/enemy review. This area therefore remains `Revisit`
until those reviews confirm the remaining matrix exceptions.
ordering remain assigned to the combat/enemy review. This area therefore
remains `Revisit` until those reviews confirm the remaining matrix
exceptions.
### NPC, Item, And Location Registries
@@ -1841,6 +1960,58 @@ mechanics that recur without erasing those distinctions.
current-source/chunk evidence, relatedness warnings, and bounded messages.
The prescribed package suite passes.
### NPC, Item, And Location Occurrences
- **End-to-end selection path:** Each extractor renders semantic registry
selectors without durable IDs, decodes a private factual occurrence
response, resolves every selection against the immutable required registry,
rejects the whole candidate on an unknown or ambiguous selector, injects the
current source ID, canonicalizes current-chunk citations, and attaches the
exact durable ID/name pair before the typed append-order merger. NPC and item
selectors are exact names because those registries prohibit comparison-name
collisions; location selectors add exact canonical evidence and bounded
cited context only for same-name records. DND-OCC-001 records the one private
response vocabulary that contradicts the shared evidence instruction.
- **Evidence and identity separation:** Registry prompt and grounding
projections omit durable/source IDs, and registry provenance is never copied
into occurrence evidence. Extract validators require direct current-source,
current-chunk evidence; normalizers and registry validators independently
re-establish exact ID/name pairs for artifacts entering through other
boundaries. Generated-reference checkpoint dependencies bind the complete
producer content/provenance while semantic registry projection digests bind
selection behavior, so an approved registry change cannot silently reuse a
stale occurrence result.
- **Canonicalization and family policy:** All three normalizers preserve nil
versus present-empty list meaning, retain invalid data long enough for
ordered diagnostics, canonicalize evidence without mutating input, sort
deterministically, collapse only exact valid-evidence duplicates, and bound
warnings. Their local policies intentionally remain distinct: NPC categories
encode factual presence/dialogue/combat roles; item identity includes
quantity and directionally constrained holders; location ordering uses an
explicit semantic kind precedence and retains same-name records with
different durable IDs. A generic occurrence normalizer would obscure these
contracts. DND-OCC-003 concerns only avoidable repeated canonicalization
inside the item implementation.
- **Boundary and reference review:** Durable codecs strictly reject unknown
fields, trailing values, absent lists, empty required values, unsupported
kinds, and item holder/quantity violations. DND-REG-001 now also covers the
shared reversed-range structural omission at the occurrence codecs. Extract
campaign context remains legitimate model grounding, while deterministic
normalizers require only their immutable registry; DND-OCC-002 records the
NPC normalizer's four inert campaign slots rather than changing extraction.
Family-specific shape, registry, source, relatedness, and invariant
validators remain separate because their ordered deferral and source-aware
responsibilities differ from durable decoding.
- **Generated handoffs and tests:** Production resolution requires an earlier
compatible generated producer or a strictly decoded compatible external
registry for each family. The representative assembled D&D flow proves exact
registry IDs, independent occurrence evidence, and distinct same-name
location selection through extraction and normalization. Extractor tests own
prompt/schema adaptation and all-or-nothing resolution; normalizer tests own
ordering, exact duplicates, holders/quantities, same-name locations, warning
order, and ownership; validator tests own pair, source, relatedness, and
invariant defenses. The prescribed occurrence and CLI suites pass.
## Validation Record
| Date | Scope | Command or check | Result |
@@ -1890,6 +2061,10 @@ mechanics that recur without erasing those distinctions.
| 2026-08-08 | Audit target integrity before registry-family review | `git diff --quiet 92e89076a268089e703978fb9d7176200e93344c..HEAD -- . ':(exclude)docs/roadmap/**'` | Pass; production target unchanged |
| 2026-08-08 | Registry-family graph/code review | Exact symbol reads, complexity queries, and call traces across NPC, item, and location extraction, canonicalization, identity, immutable registries and projections, reconciliation eligibility/application/retry/fallback, normalization, validation, codecs, prompt assets, schemas, and focused tests | DND-REG-001 through DND-REG-004 recorded; name/anchor identity, same-name location, currency, proposal safety, diagnostics, fallback, and immutable projection policies otherwise confirmed |
| 2026-08-08 | Required NPC, item, and location registry tests | `go test ./internal/modules/dnd/extract/npcregistry ./internal/modules/dnd/extract/itemregistry ./internal/modules/dnd/extract/locationregistry ./internal/modules/dnd/npcs/... ./internal/modules/dnd/items/... ./internal/modules/dnd/locations/... ./internal/modules/dnd/normalize/npcregistry ./internal/modules/dnd/normalize/itemregistry ./internal/modules/dnd/normalize/locationregistry ./internal/modules/dnd/validate/npcregistry/... ./internal/modules/dnd/validate/itemregistry/... ./internal/modules/dnd/validate/locationregistry/...` | Pass |
| 2026-08-08 | Audit target integrity before occurrence-family review | `git diff --quiet 92e89076a268089e703978fb9d7176200e93344c..HEAD -- . ':(exclude)docs/roadmap/**'` | Pass; production target unchanged |
| 2026-08-08 | Occurrence-family graph/code review | Exact symbol reads, complexity queries, and call traces across NPC, item, and location semantic registry projections/resolution, response adaptation, current-source evidence attachment, canonical ordering/deduplication, normalization, validation, codecs, prompt assets, private schemas, and generated-reference tests | DND-OCC-001 through DND-OCC-003 recorded and DND-REG-001 broadened; all-or-nothing identity attachment, evidence separation, category/holder/quantity/same-name policy, nil/empty ownership, and handoff behavior otherwise confirmed |
| 2026-08-08 | Required NPC, item, and location occurrence tests | `go test ./internal/modules/dnd/extract/npcoccurrences ./internal/modules/dnd/extract/itemoccurrences ./internal/modules/dnd/extract/locationoccurrences ./internal/modules/dnd/normalize/npcoccurrences ./internal/modules/dnd/normalize/itemoccurrences ./internal/modules/dnd/normalize/locationoccurrences ./internal/modules/dnd/validate/npcoccurrences/... ./internal/modules/dnd/validate/itemoccurrences/... ./internal/modules/dnd/validate/locationoccurrences/...` | Pass |
| 2026-08-08 | Generated occurrence handoff tests | `go test ./internal/cli` | Pass |
## Coverage Matrix
@@ -1905,7 +2080,7 @@ mechanics that recur without erasing those distinctions.
| Generic and Seriatim modules | Reviewed | Internal module guide; Seriatim, JSON output, chunk-map, and evidence-context integration contracts; all implementation/tests under `internal/modules/generic/` and `internal/modules/seriatim/`; framework evidence preparation/output paths and focused tests; maintained CLI example and production output contracts | Target-integrity check, graph architecture/symbol/call/caller review, direct import map, required module and codec tests, focused composed evidence/output tests | MOD-001, MOD-002, MOD-003 |
| Shared D&D types, codecs, and family mechanics | Revisit | D&D internal/module docs and all D&D integration contracts; root durable types; all ten codec packages and candidate JSON; shared references, ordering, citations, inputs, comparison, diagnostics, registry resolver, entity reconciliation, and assets; typed merger/evidence/default-chain/fallback/family registration; representative module asset declarations and focused tests | Target-integrity check, scoped graph architecture/search/traces, ten-family convention matrix, required codec/shared/register tests | DND-CORE-001 |
| NPC, item, and location registries | Reviewed | NPC/item/location registry integration contracts and relevant identity/evidence ADRs; extractors, candidate models and response schemas; identity, immutable registry, prompt/identity projection, location grounding, reconciliation, normalizer, validators, codecs, prompt assets, and focused tests for all three families | Target-integrity check, scoped graph architecture/complexity/search/traces, full family comparison, required extractor/identity/registry/normalizer/validator tests | DND-REG-001, DND-REG-002, DND-REG-003, DND-REG-004 |
| NPC, item, and location occurrences | Pending | — | — | — |
| NPC, item, and location occurrences | Reviewed | NPC/item/location occurrence integration contracts and deterministic opaque-ID ADR; extractors, private response models/schemas, semantic registry projections and resolvers, canonicalizers, normalizers, validator chains, codecs, prompt assets, and generated/external registry handoff tests for all three families | Target-integrity check, scoped graph architecture/complexity/search/traces, full family comparison, required extractor/normalizer/validator tests, generated CLI handoff tests | DND-REG-001, DND-OCC-001, DND-OCC-002, DND-OCC-003 |
| Spells, scene chunking, and scene descriptions | Pending | — | — | — |
| Combat turns and enemy events | Pending | — | — | — |
| Test ownership, comments, and final synthesis | Pending | — | — | — |