diff --git a/docs/cli.md b/docs/cli.md index 39a785e..b58152b 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -103,10 +103,11 @@ go run ./cmd/notarius run dnd-session \ --reference spells.extract.glossary=./campaign-glossary.txt ``` -For the maintained NPC-grounded workflow, use the explicit ordered pipeline. -The first step produces the normalized NPC artifact; the second step receives -it in memory and fans it out to spell extraction, combat extraction, and combat -normalization: +For the maintained ordered D&D workflow, use the explicit pipeline. The first +step produces normalized NPC and scene-description artifacts; the second step +receives the NPC artifact in memory for spell extraction, combat extraction, and +combat normalization, and receives the required scene-description artifact for +combat eligibility: ```sh go run ./cmd/notarius run dnd-session \ @@ -118,6 +119,10 @@ go run ./cmd/notarius run dnd-session \ The generated NPC content remains contextual grounding, not spell or combat evidence. It is represented in manifests and debug summaries by bounded identity and producer provenance, not by payload content or a filesystem path. +The scene-description artifact is control context: combat extraction calls its +LLM only for an exact `combat` scene match. See the +[D&D combat-turn artifact contract](integrations/dnd-combat-turn-artifacts.md) +for the resulting empty-output and warning behavior. The same grammar can target chunk, merge, and normalize slots when the configured modules declare them: diff --git a/docs/config.md b/docs/config.md index d5f9183..9a0b498 100644 --- a/docs/config.md +++ b/docs/config.md @@ -22,9 +22,9 @@ The explicit-path option is defined in the [CLI reference](cli.md). - [Minimal D&D configuration](../examples/dnd-minimal.config.yml) shows the shortest useful single-step, single-lane pipeline. - [Complete D&D configuration](../examples/dnd-complete.config.yml) shows scene - chunking, ordered steps, all five D&D artifact lanes, a generated NPC - handoff, campaign and spell-catalog references, checkpoint storage, and - chunk-map output. + chunking, ordered steps, all five D&D artifact lanes, generated NPC and + scene-description handoffs, campaign and spell-catalog references, checkpoint + storage, and chunk-map output. Both are complete version 3 files. The fragments below illustrate individual fields and are not alternate complete configurations. @@ -168,12 +168,19 @@ pipelines: npcs: extract: dnd/npcs normalize: dnd/npcs + scene-descriptions: + extract: dnd/scene-descriptions + normalize: dnd/scene-descriptions - id: grounded-events references: npcs: artifact: step: identify-npcs lane: npcs + scene_descriptions: + artifact: + step: identify-npcs + lane: scene-descriptions artifacts: spells: extract: dnd/spells @@ -374,7 +381,7 @@ production validators do not call the LLM and must not set `llm_profile`. | chunk | `dnd/scenes` | Uses an LLM to split transcript source units into D&D scenes. | | extract | `dnd/spells` | Extracts typed D&D spell-list artifacts. | | extract | `dnd/npcs` | Extracts typed D&D NPC-list artifacts. | -| extract | `dnd/combat-turns` | Extracts typed D&D combat-turn-list artifacts. | +| extract | `dnd/combat-turns` | Extracts typed D&D combat-turn-list artifacts only for exact combat scene matches. | | extract | `dnd/npc-interactions` | Extracts typed D&D NPC-interaction-list artifacts from a supplied NPC registry. | | extract | `dnd/scene-descriptions` | Extracts one typed D&D scene description for each accepted chunk. | | merge | `appendorder` | Combines typed artifacts in chunk order. | @@ -574,14 +581,23 @@ accepts no references. No NPC registry or generated artifact is required. See the [D&D scene-description artifact contract](integrations/dnd-scene-description-artifacts.md) and the copyable [complete D&D configuration](../examples/dnd-complete.config.yml). -The `dnd/combat-turns` extractor declares the optional campaign slots and the -structured `npcs` slot. Campaign references guide only the LLM extraction -stage. The deterministic normalizer declares only `npcs`, whose operation-time -registry supports the same actor canonicalization. Each `npcs` slot -accepts exactly one UTF-8 `application/json` artifact no larger than 1 MiB. The -registry's source ranges remain provenance for the reference and never become -combat evidence. An ordered step binding fans the same generated NPC artifact -out to extraction and normalization: +The `dnd/combat-turns` extractor declares the optional campaign slots, the +optional structured `npcs` slot, and the required `scene_descriptions` slot. +Campaign references guide only the LLM extraction stage. The deterministic +normalizer declares only `npcs`, whose operation-time registry supports the +same actor canonicalization. Each `npcs` slot accepts exactly one UTF-8 +`application/json` artifact no larger than 1 MiB. The registry's source ranges +remain provenance for the reference and never become combat evidence. + +`scene_descriptions` accepts exactly one approved +`dnd/scene-description-list` artifact with media type `application/json`, no +larger than 1 MiB (1048576 bytes). Pipeline resolution rejects a combat +extractor whose required slot is unbound. The scene artifact is eligibility +control context only; it is neither prompt input nor combat evidence, and the +combat normalizer does not accept it. + +An ordered step binds the generated NPC artifact to extraction and normalization +and the generated scene-description artifact to combat extraction: ```yaml references: @@ -589,6 +605,10 @@ references: artifact: step: identify-npcs lane: npcs + scene_descriptions: + artifact: + step: identify-npcs + lane: scene-descriptions ``` When bound, the combat extractor and normalizer receive the generated registry @@ -597,6 +617,9 @@ kind, schema identity, media type, canonical digest, size, and bounded producer identity; names, content, and paths are not recorded there. When absent, the combat prompt receives the exact empty registry value `{"npcs":[]}` with its projection digest and no registry provenance. +The complete example uses the same explicit scene binding; an external approved +scene-description artifact may be used instead when the workflow crosses a +process or session boundary. Both `dnd/npc-interactions` stages require the structured `npcs` slot. Bind one accepted normalized NPC artifact from an earlier ordered step; the interaction diff --git a/docs/integrations/dnd-combat-turn-artifacts.md b/docs/integrations/dnd-combat-turn-artifacts.md index c854a03..6ffdf22 100644 --- a/docs/integrations/dnd-combat-turn-artifacts.md +++ b/docs/integrations/dnd-combat-turn-artifacts.md @@ -73,15 +73,29 @@ The standalone extractor uses these identities: | Private response-schema ID | `notarius.dnd.combat_turns.llm` | | Default profile | `gemini-2-flash` | -It requires `chunks` and `source.transcript`, accepts no options, and makes one -structured completion for each supplied chunk. The prompt receives the -chunk-scoped transcript plus the existing `players`, `party`, and `glossary` -inputs, and optionally the deprecated `roster` reference through the shared -party mapping. The optional `npcs` reference is an approved normalized NPC -artifact used only for identity grounding; it never supplies combat evidence. -An external file is validated during preparation. In an ordered pipeline, the -same slot may receive the producer's canonical generated artifact at the step -handoff. +It requires `chunks` and `source.transcript`, accepts no options, and requires +one `scene_descriptions` reference. That reference must be exactly one approved +`dnd/scene-description-list` artifact with media type `application/json` and a +maximum size of 1 MiB (1048576 bytes). It may be an external file validated +during preparation or a canonical generated artifact supplied at an ordered +step handoff. An unbound slot is a configuration error. + +The scene artifact controls eligibility, not evidence. The extractor calls the +LLM only when exactly one record has the current chunk's ID, source ID, start +unit ID, and end unit ID, and that record has `kind: combat`. An exact +`narrative`, `recap`, or `meta` record returns an accepted empty +`combat_turns` array without an LLM call, warning, or retry attempt. A missing +or mismatched exact record returns the same accepted empty result without an +LLM call or retry and emits one content-safe +`scene_classification_unavailable` warning. The scene artifact, its title and +summary, and its source references are never copied into combat turns. + +For an eligible combat chunk, the prompt receives the chunk-scoped transcript +plus the existing `players`, `party`, and `glossary` inputs, and optionally the +deprecated `roster` reference through the shared party mapping. The optional +`npcs` reference is an approved normalized NPC artifact used only for identity +grounding; it never supplies combat evidence. `scene_descriptions` is never a +combat prompt input. The private response envelope has the same turn fields and JSON types as the durable shape except that source references contain only `start_unit_id` @@ -151,13 +165,16 @@ merge validator chain. ## Production manifest and references The selectable lane uses extractor and normalizer key `dnd/combat-turns`, -`appendorder` for the typed merger, and the durable codec above. A bound `npcs` -reference contributes raw-file provenance to the run manifest. A generated -binding contributes artifact kind, schema identity, media type, canonical -digest, size, and bounded producer provenance. Consumer metadata and checkpoint -fingerprints contain no registry names, content, paths, or NPC source ranges. -The component-local registry fingerprint covers only the names projected to the -consumer, while manifest provenance retains the full artifact digest. The -normalized lane is emitted as `lanes/.json` by the JSON -output module, and warnings and rejection summaries remain in their shared -companion files. +`appendorder` for the typed merger, and the durable codec above. Bound external +references contribute raw-file provenance to the run manifest. Generated +bindings contribute artifact kind, schema identity, media type, canonical +digest, size, and bounded producer provenance. This includes the generated +scene-description artifact for the combat extractor. Consumer metadata and +checkpoint fingerprints contain no reference names, content, paths, source +ranges, scene titles, or scene summaries. For an external scene artifact, +component metadata records the gate policy plus a semantic eligibility digest +and record count; generated scene identity remains in framework handoff +provenance and dependencies. The eligibility digest changes with scene ID, +exact source range, or kind, but not with title or summary. The normalized lane +is emitted as `lanes/.json` by the JSON output module, and warnings +and rejection summaries remain in their shared companion files. diff --git a/docs/integrations/dnd-npc-artifacts.md b/docs/integrations/dnd-npc-artifacts.md index 8352def..aad1ef2 100644 --- a/docs/integrations/dnd-npc-artifacts.md +++ b/docs/integrations/dnd-npc-artifacts.md @@ -109,12 +109,19 @@ steps: npcs: extract: dnd/npcs normalize: dnd/npcs + scene-descriptions: + extract: dnd/scene-descriptions + normalize: dnd/scene-descriptions - id: grounded-events references: npcs: artifact: step: identify-npcs lane: npcs + scene_descriptions: + artifact: + step: identify-npcs + lane: scene-descriptions artifacts: spells: extract: dnd/spells @@ -124,13 +131,16 @@ steps: normalize: dnd/combat-turns ``` -The framework hands only an accepted normalized artifact across the barrier. It -validates the canonical bytes against each consumer slot and clones the -operation-time reference for the spell and combat consumers. Generated +The framework hands only accepted normalized artifacts across the barrier. It +validates the canonical bytes against each consumer slot and clones the NPC +operation-time reference for spell and combat consumers. The accompanying +scene-description reference is required by the combat extractor for eligibility +only; its consumer contract is defined in the +[D&D combat-turn artifact contract](dnd-combat-turn-artifacts.md). Generated provenance records the artifact kind, schema identity, media type, canonical -digest, size, and producer step/lane/module, but not names, source -ranges, or payload bytes. External normalized files remain supported as -explicit references and retain their file provenance. +digest, size, and producer step/lane/module, but not names, source ranges, or +payload bytes. External normalized files remain supported as explicit references +and retain their file provenance. NPC source references are registry provenance and are never accepted as spell or combat evidence. Current transcript units remain the only event evidence. diff --git a/docs/integrations/dnd-scene-description-artifacts.md b/docs/integrations/dnd-scene-description-artifacts.md index 9224709..35c6725 100644 --- a/docs/integrations/dnd-scene-description-artifacts.md +++ b/docs/integrations/dnd-scene-description-artifacts.md @@ -118,3 +118,13 @@ Use `dnd/scenes` to form accepted scene chunks, then select [complete D&D configuration](../../examples/dnd-complete.config.yml) includes this lane alongside the other D&D artifacts. Selectable keys and default validator chains are defined in [Configuration](../config.md). + +## Downstream combat use + +The combat-turn extractor consumes this approved artifact as required +eligibility control context through an explicit ordered reference binding. It +uses only an exact chunk ID and source-range match with `kind: combat` to permit +combat extraction; titles, summaries, and scene references do not become combat +prompt material or evidence. The complete downstream behavior, including empty +results and warnings for unavailable coverage, is defined in the +[D&D combat-turn artifact contract](dnd-combat-turn-artifacts.md). diff --git a/docs/internal/modules.md b/docs/internal/modules.md index 9da6adb..26c731d 100644 --- a/docs/internal/modules.md +++ b/docs/internal/modules.md @@ -123,6 +123,28 @@ shared `internal/modules/dnd/codec/candidatejson` package supplies strict typed candidate JSON mechanics; each artifact codec retains its own durable schema and approved-value policy. +### `internal/modules/dnd/scenedescriptions/registry` + +The scene-description registry owns the required `scene_descriptions` control +reference used by combat extraction. It decodes exactly one approved scene-list +artifact through the scene-description codec and retains only scene ID, exact +source reference, and kind. Titles, summaries, original bytes, paths, and +prompt material do not cross this domain boundary. + +An external reference is validated during preparation; an unbound seed is +permitted only while a configured generated reference awaits the ordered +handoff. At operation time, a generated artifact overrides the seed and is +resolved into an immutable view safe for concurrent extract jobs. Matching is +strictly exact by chunk ID, source ID, start unit ID, and end unit ID, producing +an exact, missing, or mismatched result. Only an exact result exposes kind. + +The registry's semantic eligibility digest is derived from a sorted projection +of ID, exact range, and kind. It ignores titles, summaries, and input order; +the unbound view has a stable empty projection digest. Combat extractor +metadata and checkpoint identity use this semantic boundary for external +references, while generated artifact identity and dependencies remain owned by +the framework handoff. + The `internal/modules/dnd/codec/combatturns` package owns the durable `dnd/combat-turn-list` schema and candidate versus approved JSON boundary. It is registered by the production D&D family registrar for the selectable combat @@ -293,18 +315,31 @@ checks. The durable contract is defined in the ### `internal/modules/dnd/extract/combatturns` -The combat extractor prepares one structured request per supplied chunk using -the shared extraction-evidence, identity, campaign-reference, NPC-grounding, -and transcript prompt inputs. It -maps the private response to `dnd.CombatTurnList`, assigns the current source -identity, removes exact duplicate source ranges, and orders turns by valid -source-document position while preserving malformed candidate fields for -deterministic validators. Its package-owned private response schema enforces -only the structural JSON envelope; semantic artifact constraints remain with -the validator chain. Its prepared metadata and checkpoint fingerprints contain -only prompt/schema/mapping identities plus an optional NPC registry digest. -The prompt follows the shared D&D extraction ordering and cache policy -documented in +The combat extractor requires the `scene_descriptions` reference and resolves +it through the immutable scene-description registry before it resolves NPC +grounding or constructs prompt inputs. It calls the LLM only for an exact +current-chunk match whose kind is `combat`. Exact `narrative`, `recap`, and +`meta` matches return an accepted empty `dnd.CombatTurnList`; missing or +mismatched coverage returns the same result with one bounded unavailable- +classification warning. These deterministic results do not consume retry +attempts. Scene descriptions are control context only and are not passed to the +combat prompt or copied into combat evidence. + +For eligible chunks, the extractor prepares one structured request using the +shared extraction-evidence, identity, campaign-reference, NPC-grounding, and +transcript prompt inputs. It maps the private response to +`dnd.CombatTurnList`, assigns the current source identity, removes exact +duplicate source ranges, and orders turns by valid source-document position +while preserving malformed candidate fields for deterministic validators. Its +package-owned private response schema enforces only the structural JSON +envelope; semantic artifact constraints remain with the validator chain. + +Prepared metadata and checkpoint fingerprints include prompt, response-schema, +mapping, and scene-gate identities. An external scene reference additionally +reports its semantic eligibility digest and count; generated identity remains +framework handoff provenance and dependency state. Neither surface retains +scene prose or payload bytes. The prompt follows the shared D&D extraction +ordering and cache policy documented in [LLM Runtime](llm.md#dd-extraction-prompt-ordering-and-cache-boundaries). The package exposes typed registration and is included in the production D&D registrar with the default combat extraction chain. diff --git a/docs/internal/overview.md b/docs/internal/overview.md index e312c3a..6279d66 100644 --- a/docs/internal/overview.md +++ b/docs/internal/overview.md @@ -98,7 +98,7 @@ Configuration. The implemented module packages are: | `internal/modules/dnd/codec/scenedescriptions` | Strictly decodes and stably encodes the durable D&D scene-description-list representation. | | `internal/modules/dnd/extract/spells` | Maps private structured model output to canonical source-grounded D&D spell lists. | | `internal/modules/dnd/extract/npcs` | Maps private structured model output to canonical source-grounded D&D NPC lists. | -| `internal/modules/dnd/extract/combatturns` | Maps private structured model output to source-grounded D&D combat-turn candidates and preserves chronology and invalid candidate values for validators. | +| `internal/modules/dnd/extract/combatturns` | Uses exact scene eligibility to select combat chunks, then maps private structured model output to source-grounded D&D combat-turn candidates. | | `internal/modules/dnd/extract/npcinteractions` | Maps private structured model output to current-source NPC interaction candidates grounded by a required registry. | | `internal/modules/dnd/extract/scenedescriptions` | Maps one private scene description to the current accepted chunk's ID and exact range. | | `internal/modules/dnd/npcinteractions` | Owns interaction occurrence ordering, valid-evidence checks, and exact interaction identity shared by normalization and invariant validation. | @@ -109,6 +109,7 @@ Configuration. The implemented module packages are: | `internal/modules/dnd/validate/npcinteractions` | Provides deterministic shape, registry, source-reference, source-relatedness, and normalized-invariant validation for interaction chains. | | `internal/modules/dnd/validate/scenedescriptions` | Provides deterministic shape, exact extraction attachment, source-relatedness, and normalized-invariant validation for scene-description chains. | | `internal/modules/dnd/npcs/registry` | Resolves validated normalized NPC references into immutable grounding data and exact identity lookup. | +| `internal/modules/dnd/scenedescriptions/registry` | Resolves approved scene descriptions into immutable exact-match combat eligibility data without retaining scene prose. | | `internal/modules/dnd/npcs/identity` | Owns Unicode-aware NPC identity, ID derivation, and registry collision validation. | | `internal/modules/dnd/spells/catalog` | Embeds and validates the versioned D&D 5e 2014 SRD catalog, composes optional overlays, and provides immutable effective lookup. | | `internal/modules/generic/merge/appendorder` | Combines accepted extraction results in chunk order. | diff --git a/docs/operations.md b/docs/operations.md index 507cc69..973e97a 100644 --- a/docs/operations.md +++ b/docs/operations.md @@ -53,7 +53,8 @@ contains one pipeline with two ordered steps. The first step extracts and normalizes NPCs and scene descriptions. Only after those lanes reach accepted terminal results does the second step begin; its generated NPC reference is supplied in memory to spell, combat-turn, and NPC-interaction extraction and -the applicable normalizers. +the applicable normalizers, while its generated scene-description reference is +supplied to combat-turn extraction. ```sh go run ./cmd/notarius run dnd-session \ @@ -70,6 +71,14 @@ exposed through a filesystem path. The same producer artifact may fan out to compatible consumers, while a missing or rejected producer prevents the later step from starting. +Combat-turn extraction calls its LLM only when a scene record exactly matches +the accepted chunk and has kind `combat`. Exact `narrative`, `recap`, and +`meta` records produce an accepted empty combat-turn result without an LLM call. +Missing or mismatched scene coverage also produces an accepted empty result and +a bounded warning. Scene descriptions remain control context rather than combat +evidence or prompt material; the complete behavior is defined by the +[D&D combat-turn artifact contract](integrations/dnd-combat-turn-artifacts.md). + Standalone module configurations continue to support external NPC files when a workflow intentionally crosses a process or session boundary. Those files are validated against the consumer slot and must be protected as sensitive diff --git a/docs/roadmap/future.md b/docs/roadmap/future.md index 5b8db00..22395d1 100644 --- a/docs/roadmap/future.md +++ b/docs/roadmap/future.md @@ -18,10 +18,6 @@ not as committed release dates. ### Use D&D Scene Chunking -- Allow the combat extractor to no-op for chunks classified as non-combat only - after the scene-description artifact can be supplied through an explicit - ordered dependency. Do not make generic chunk materialization depend on a D&D - classification. - Use ordered pipeline steps whenever a later artifact needs an accepted earlier artifact as context. Keep independent lanes in the same step and do not introduce a general DAG or concurrent cross-lane reconciliation model. diff --git a/docs/roadmap/scene-aware-combat-extraction.md b/docs/roadmap/scene-aware-combat-extraction.md index f9880ac..59c8051 100644 --- a/docs/roadmap/scene-aware-combat-extraction.md +++ b/docs/roadmap/scene-aware-combat-extraction.md @@ -2,7 +2,9 @@ ## Status -Proposed near-term scope. +Implemented. This document preserves the feature contract and rationale; the +current configuration, operational, integration, and internal behavior is +maintained in their canonical documentation. ## Purpose @@ -129,8 +131,7 @@ The maintained complete D&D example should bind the normalized `scene-descriptions` lane from the first step to the `scene_descriptions` slot in the second step. The minimal example should remain unchanged. -When implemented, current-behavior documentation should be updated in its -canonical locations: +Current-behavior documentation is maintained in these canonical locations: - Configuration owns the new selectable reference slot and binding example. - Operations owns the ordered scene-aware workflow.