Harmonize D&D artifact contracts

This commit is contained in:
2026-07-26 13:43:45 +00:00
parent 2f506f4985
commit f6981e2264
6 changed files with 281 additions and 800 deletions

View File

@@ -1,9 +1,10 @@
# D&D Scene Description Artifact Contract
# D&D Scene-Description Artifact
This document defines the durable `dnd/scene-description-list` artifact
emitted by the D&D scene-description lane.
This contract defines the durable output of `dnd/scene-descriptions`. Each
record classifies one accepted transcript chunk and gives it a minimal
source-grounded title and summary.
## Artifact identity
## Identity and compatibility
| Property | Value |
| --- | --- |
@@ -13,38 +14,32 @@ emitted by the D&D scene-description lane.
| Schema version | `v1` |
| Media type | `application/json` |
The normalized payload is written by the JSON output module to
`lanes/<lane-id>.json`. See [JSON output](json-output.md) for the surrounding
output bundle.
`v1` is a strict JSON object with required non-empty `scenes`. Scene and
source-reference objects reject unknown fields. A future incompatible shape
requires a new schema version.
## JSON shape
## Wire shape
The payload is a JSON object containing exactly one required field, `scenes`.
Each scene object contains exactly these required fields:
Each scene has exactly these required fields:
| Field | Shape and ownership |
| Field | Contract |
| --- | --- |
| `id` | Non-empty accepted chunk ID, assigned by Notarius. |
| `source_ref` | Exact inclusive accepted chunk range, assigned by Notarius. |
| `kind` | One of `combat`, `narrative`, `recap`, or `meta`. |
| `source_ref` | The assigned inclusive source range for that chunk. |
| `kind` | `combat`, `narrative`, `recap`, or `meta`. |
| `title` | Non-empty, trimmed, source-grounded title. |
| `summary` | Non-empty, trimmed, source-grounded summary. |
All object layers reject unknown fields. The `scenes` array must be present and
non-empty. `source_ref` has exactly `source_id`, `start_unit_id`, and
`end_unit_id`; its source ID is non-empty and its unit IDs are positive
integers.
`source_ref` has exactly `source_id`, `start_unit_id`, and `end_unit_id`.
Its source ID identifies the input transcript; its positive unit IDs identify
the chunk's inclusive range, with the start no later than the end.
```json
{
"scenes": [
{
"id": "chunk-000001",
"source_ref": {
"source_id": "session-alpha",
"start_unit_id": 1,
"end_unit_id": 3
},
"source_ref": {"source_id": "session-7", "start_unit_id": 1, "end_unit_id": 3},
"kind": "narrative",
"title": "Arrival at the watchtower",
"summary": "The party reaches the ruined watchtower and begins to investigate it."
@@ -53,78 +48,22 @@ integers.
}
```
`id` and `source_ref` are application-owned identity and evidence. The model
provides only `kind`, `title`, and `summary`; it is not asked for chunk IDs,
source IDs, unit IDs, ranges, participants, or confidence.
## Meaning and normalized form
## Scene kinds
`combat` identifies a chunk where active combat is the central activity.
`narrative` is current in-world play that is not principally combat, recap, or
meta discussion. `recap` is primarily a recounting of an earlier session, and
`meta` is primarily out-of-character discussion. The artifact does not add
participants, confidence, events, or information absent from the chunk.
| Kind | Meaning |
| --- | --- |
| `combat` | Active combat is a substantive central activity. |
| `narrative` | Current-session in-world play that is not principally combat, recap, or meta discussion. |
| `recap` | The table is primarily recounting a previous session. |
| `meta` | Sustained out-of-character discussion is the scene's primary purpose. |
Normalization trims title and summary, orders scenes by source position and
then ID, and removes exact duplicate records. A reused ID with different
durable fields, or the same source range with different kind, title, or
summary, is invalid. It does not merge adjacent ranges, alter prose, or infer
missing scenes.
For a mixed accepted chunk, classification prefers `combat`, then `recap`,
then `meta`, then `narrative`. Brief table talk, rules clarification, or a
short recollection does not replace the main current-session activity.
## Extraction and evidence
The extractor runs once for each accepted chunk and maps one successful model
response to one scene record. It copies the current chunk ID and exact chunk
range, preserves the model kind without repair, and trims only surrounding
whitespace from title and summary. A model response cannot represent an empty
result; extraction failure follows the configured retry and rejection policy.
Optional `players`, `party`, and `glossary` campaign references can help
disambiguate names or setting terms. They never supply scene evidence or add
events absent from the accepted chunk. The lane requires no NPC registry or
other generated artifact reference.
## Merge and normalization
Accepted per-chunk lists are appended in chunk order. Normalization then:
1. validates the current-source range, non-empty ID and prose, and closed kind;
2. trims only title and summary whitespace;
3. sorts records by source-document start position, then ID;
4. removes records only when all five durable fields are identical;
5. rejects a reused ID when any remaining durable field differs; and
6. rejects the same exact range when `kind`, `title`, or `summary` differs.
Two different IDs with the same range and identical model-owned content remain
separate records. Normalization does not join adjacent ranges, rewrite prose,
repair kinds, infer missing scenes, or use chunk annotations.
## Validation and warnings
Extraction validation requires exactly one record with an ID and range exactly
equal to its current chunk. Later validation checks source membership without a
current chunk. Shape, source-range, kind, ID, and normalized-invariant failures
reject the artifact.
Relatedness checks are advisory. They separately warn when a scene title or
summary has no significant lexical token in its cited transcript range. The
check ignores short tokens and common function words, uses transcript text only,
and does not treat campaign references as evidence. Warning diagnostics are
bounded and do not copy transcript or campaign-reference content.
## Configuration
Use `dnd/scenes` to form accepted scene chunks, then select
`dnd/scene-descriptions` for extraction and normalization. The maintained
[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).
The [combat-turn artifact](dnd-combat-turn-artifacts.md) uses an exact matching
`combat` scene only as eligibility control; scene title, summary, and source
reference never become combat evidence. Publication is defined by the
[JSON output contract](json-output.md); implementation details live in
[D&D module internals](../internal/dnd.md).