# D&D Combat-Turn Artifact Contract This document defines the durable artifact and serialization boundary for D&D combat turns. It does not define extraction, validation beyond the codec's structural checks, normalization, prompts, or a selectable pipeline lane. ## 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`.