# D&D Combat-Turn Artifact Contract This document defines the durable artifact, serialization, extraction, and candidate-validation boundaries for D&D combat turns. Normalization and a selectable production pipeline lane are not part of this contract yet. ## Artifact identity | Property | Value | | --- | --- | | Artifact kind | `dnd/combat-turn-list` | | Schema ID | `notarius.dnd.combat_turns` | | Schema name | `notarius_dnd_combat_turns_v1` | | Schema version | `v1` | | Media type | `application/json` | The top-level JSON object contains the required `combat_turns` array, which may be empty. Every object rejects unknown fields. ## JSON shape Each combat turn contains these required fields: | Field | Shape | | --- | --- | | `actor` | Non-empty string. | | `turn_kind` | One of `turn`, `reaction`, `legendary_action`, `lair_action`, or `other`. | | `round` | Required JSON field containing a positive integer or `null`. | | `actions` | Required array with at least one action. | | `summary` | Non-empty string. | | `source_refs` | Required array with at least one source reference. | Each action contains these required fields: | Field | Shape | | --- | --- | | `category` | One of `attack`, `spell`, `movement`, `item`, `ability_check`, `saving_throw`, `condition`, or `other`. | | `declaration` | Non-empty string describing what was declared. | | `targets` | Required array of strings; the array may be empty, but entries may not be empty. | | `resolution` | Required JSON field containing a non-empty string or `null`. | Source references use the shared source-reference shape: ```json { "source_id": "session-alpha", "start_unit_id": 1, "end_unit_id": 2 } ``` `source_id` must be non-empty and both unit IDs must be positive integers. The codec does not resolve references against a source document or enforce source range ordering; those checks belong to the later source-reference validation boundary. ## Codec behavior The codec exposes two representations of the same typed artifact: - Candidate encode/decode preserves invalid enum values, nullable values, required-array presence, required strings, targets, and source references so later validators can report them. Candidate decoding still requires valid JSON, one JSON value, known fields, and the explicitly present `round` and `resolution` keys; `null` is distinct from a missing key. - Approved encode/decode enforces the structural rules in this contract. The codec owns the durable JSON Schema, whose object layers all set `additionalProperties` to `false`. Codec metadata contains only `combat_turn_count`. The maintained compact fixture is `internal/modules/dnd/codec/combatturns/testdata/dnd_combat_turns.v1.json`. ## Extraction boundary The standalone extractor uses these identities: | Property | Value | | --- | --- | | Extractor key | `dnd/combat-turns` | | Capability | `dnd.combat_turns` | | Prompt ID | `dnd.combat_turns` | | Prompt version | `v1` | | Private response-schema key | `dnd_combat_turns_llm` | | 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. The private response shape is the same as the durable turn/action shape except that source references contain only `start_unit_id` and `end_unit_id`. The extractor assigns the current source ID, removes exact duplicate ranges, and stable-sorts turns by the earliest valid source-document position. Numeric unit IDs are identifiers; source-document slice position determines chronology. Malformed candidate fields remain in the typed result for deterministic validators to report. ## Deterministic candidate validation The standalone validator keys are: | Validator | Responsibility | | --- | --- | | `extract/dnd/combat-turns/shape` | Required arrays, strings, nullable fields, positive rounds, and supported enum values. | | `extract/dnd/combat-turns/source_refs` | Source identity, source-unit existence, and range order through the source document. | | `extract/dnd/combat-turns/source_relatedness` | At most one advisory warning per turn when the actor or declared action is not related to cited transcript text. | Source-reference and relatedness validators defer malformed shape to the shape validator. Relatedness also defers when any cited source range is invalid. It combines overlapping cited ranges once in document order, compares actors with the shared Unicode-aware NPC identity policy, and checks declaration tokens of at least four Unicode code points against complete cited-text tokens. Targets are not checked deterministically. The extractor and validators are package-complete but are not registered by the production D&D family registrar yet. Normalization, production composition, and selectable configuration are defined when implemented.