Document scene-aware combat extraction

This commit is contained in:
2026-07-25 19:34:33 +00:00
parent b1c0faa748
commit 3da20e9d6a
10 changed files with 169 additions and 62 deletions

View File

@@ -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:

View File

@@ -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

View File

@@ -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/<lane-id>.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/<lane-id>.json` by the JSON output module, and warnings
and rejection summaries remain in their shared companion files.

View File

@@ -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.

View File

@@ -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).

View File

@@ -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.

View File

@@ -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. |

View File

@@ -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

View File

@@ -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.

View File

@@ -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.