Harmonize D&D artifact contracts
This commit is contained in:
@@ -1,160 +1,69 @@
|
||||
# D&D NPC Artifact
|
||||
|
||||
This document defines the durable D&D NPC-list artifact, its JSON codec, and
|
||||
the selectable production NPC pipeline. The normalized JSON payload can be
|
||||
passed explicitly to the spell extractor as an optional caster-name registry
|
||||
or to the combat extractor and normalizer as an actor registry. It
|
||||
remains a reference, not spell or combat evidence.
|
||||
The NPC interaction extractor and normalizer also consume this registry for
|
||||
canonical identity; registry source references remain provenance and never
|
||||
become interaction evidence. Their occurrence contract is defined in the
|
||||
[D&D NPC interaction artifact](dnd-npc-interaction-artifacts.md).
|
||||
This contract defines the durable NPC registry produced by `dnd/npcs`. It is a
|
||||
minimal, source-grounded identity registry for other D&D artifacts, not a
|
||||
character sheet or a relationship summary.
|
||||
|
||||
## Identity
|
||||
## Identity and compatibility
|
||||
|
||||
- Artifact kind: `dnd/npc-list`
|
||||
- Durable schema ID: `notarius.dnd.npcs`
|
||||
- Durable schema name: `notarius_dnd_npcs_v1`
|
||||
- Durable schema version: `v1`
|
||||
- Media type: `application/json`
|
||||
- Identity policy: `dnd.npcs.identity.v1`
|
||||
| Property | Value |
|
||||
| --- | --- |
|
||||
| Artifact kind | `dnd/npc-list` |
|
||||
| Schema ID | `notarius.dnd.npcs` |
|
||||
| Schema name | `notarius_dnd_npcs_v1` |
|
||||
| Schema version | `v1` |
|
||||
| Media type | `application/json` |
|
||||
| Identity policy | `dnd.npcs.identity.v1` |
|
||||
|
||||
The durable JSON Schema is owned by the D&D NPC codec. NPC IDs are derived from
|
||||
the Unicode-normalized, case-folded canonical name using the identity policy.
|
||||
The durable codec enforces the artifact shape and ID syntax; registry identity
|
||||
validation remains a separate deterministic concern.
|
||||
`v1` accepts one strict JSON object with required `npcs`; the array may be
|
||||
empty. NPC and source-reference objects reject unknown fields. A future
|
||||
incompatible artifact shape or identity policy uses a new version or policy.
|
||||
|
||||
The extractor's private LLM response schema is a separate structural transport
|
||||
contract. It omits framework-assigned NPC and source IDs and admits semantic
|
||||
candidates for the deterministic shape and source-reference validators; it is
|
||||
not part of this durable contract.
|
||||
## Wire shape and identity
|
||||
|
||||
## Output Shape
|
||||
Each NPC has these required fields:
|
||||
|
||||
The payload is one object with a required top-level `npcs` array:
|
||||
| Field | Contract |
|
||||
| --- | --- |
|
||||
| `id` | `npc:sha256:` followed by 64 lowercase hexadecimal characters. |
|
||||
| `name` | Non-empty canonical display name. |
|
||||
| `source_refs` | One or more transcript evidence ranges for the identity. |
|
||||
|
||||
A source reference has exactly `source_id`, `start_unit_id`, and `end_unit_id`.
|
||||
The source ID identifies the transcript, unit IDs are positive inclusive unit
|
||||
identifiers, and the start may not follow the end.
|
||||
|
||||
```json
|
||||
{"npcs": []}
|
||||
{
|
||||
"npcs": [
|
||||
{
|
||||
"id": "npc:sha256:99a16589618a04f535a7d21fdcc71a0b1c05d22f752cd492065b1086d97bc3d7",
|
||||
"name": "Mira Thorn",
|
||||
"source_refs": [
|
||||
{"source_id": "session-7", "start_unit_id": 4, "end_unit_id": 5}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
The array may be empty. Every object and nested object rejects unknown fields.
|
||||
The ID is deterministic: normalize the name to Unicode NFKC, normalize the
|
||||
supported apostrophe forms, collapse whitespace, case-fold it, SHA-256 the
|
||||
result, then prefix the lowercase hexadecimal digest with `npc:sha256:`. Each
|
||||
canonical identity and ID appears at most once. Normalization collapses records
|
||||
with the same canonical identity, retains their earliest position, and merges
|
||||
their canonicalized evidence; it does not add aliases, roles, descriptions, or
|
||||
relationship fields.
|
||||
|
||||
## NPC Fields
|
||||
## Scope and consumers
|
||||
|
||||
Each NPC contains exactly these required fields:
|
||||
Only individually identifiable NPC names with transcript evidence belong in
|
||||
this artifact. Groups, generic roles, invented labels, and descriptive
|
||||
enrichment are excluded. Its source references prove registry provenance; they
|
||||
do not become evidence for a spell, interaction, or combat occurrence.
|
||||
|
||||
- `id`: `npc:sha256:` followed by 64 lowercase hexadecimal characters;
|
||||
- `name`: the canonical display name;
|
||||
- `source_refs`: at least one source reference supporting the NPC record.
|
||||
|
||||
Each source reference contains required `source_id`, `start_unit_id`, and
|
||||
`end_unit_id`; unit IDs are positive integers. Source document identity, unit
|
||||
existence, and range ordering are validated by the source-reference validator
|
||||
when the artifact is used by a pipeline.
|
||||
|
||||
## Codec Boundary
|
||||
|
||||
`EncodeCandidate` and `DecodeCandidate` provide strict single-value JSON
|
||||
serialization while preserving typed values that still need semantic
|
||||
validation. `Encode` and `Decode` are the approved-artifact boundary and
|
||||
require all durable structural fields, non-empty required strings, valid source
|
||||
reference shapes, and the NPC ID pattern.
|
||||
|
||||
Codec metadata contains only `npc_count`. Schema bytes and returned metadata
|
||||
are independent values so callers cannot mutate codec-owned state.
|
||||
|
||||
## Production Pipeline
|
||||
|
||||
The production identities are:
|
||||
|
||||
- extractor: `dnd/npcs`;
|
||||
- artifact kind: `dnd/npc-list`;
|
||||
- normalizer: `dnd/npcs`; and
|
||||
- durable schema: `notarius.dnd.npcs`, version `v1`, media type
|
||||
`application/json`.
|
||||
|
||||
The extractor maps private model records to the current source identity and
|
||||
assigns deterministic IDs. Extraction validation checks shape, source
|
||||
references, and source relatedness. The normalizer first consolidates equal
|
||||
canonical-name matches, then may make one document-level LLM-assisted identity
|
||||
decision per configured normalize attempt for eligible distinctly named
|
||||
records. Consolidation is name-based: it retains a supplied canonical display
|
||||
name, keeps the earliest affected output position, derives its ID again, and
|
||||
unions exact evidence in canonical order. Ambiguous, invalid, or conflicting
|
||||
proposals are not applied; independently safe matches may still be retained.
|
||||
After the retry budget is exhausted, the safe result is accepted with bounded
|
||||
normalization warnings and the usual validation. The durable v1 artifact shape
|
||||
does not add aliases, proposal fields, or any other semantic-normalization
|
||||
representation.
|
||||
|
||||
The extraction prompt asks only for individually identifiable NPC names backed
|
||||
by source evidence. Groups, generic roles, invented labels, and descriptive or
|
||||
relationship enrichment are outside the contract.
|
||||
|
||||
The default extraction chain is `generic/valid_json`,
|
||||
`extract/dnd/npcs/shape`, `extract/dnd/npcs/source_refs`,
|
||||
`generic/valid_json_schema`, and `extract/dnd/npcs/source_relatedness`. The
|
||||
default normalize chain is `generic/valid_json`, `extract/dnd/npcs/shape`,
|
||||
`normalize/dnd/npcs/identity`, `extract/dnd/npcs/source_refs`,
|
||||
`generic/valid_json_schema`, and `extract/dnd/npcs/source_relatedness`.
|
||||
Relatedness emits bounded warnings when an NPC canonical name is not present
|
||||
near its cited transcript text; opaque campaign
|
||||
references may explain such a warning but do not become evidence.
|
||||
|
||||
## Manifest And Artifact Handoff
|
||||
|
||||
The NPC extractor records prompt and response-schema identities. The durable
|
||||
codec records only `npc_count`; raw names, source references, and payload bytes
|
||||
stay in the lane file rather than manifest
|
||||
metadata. The normalized lane can be consumed by a later ordered step through
|
||||
the registered canonical codec:
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- id: identify-npcs
|
||||
artifacts:
|
||||
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
|
||||
normalize: dnd/spells
|
||||
combat:
|
||||
extract: dnd/combat-turns
|
||||
normalize: dnd/combat-turns
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
NPC source references are registry provenance and are never accepted as spell
|
||||
or combat evidence. Current transcript units remain the only event evidence.
|
||||
|
||||
Consumers receive a separate names-only projection in normalized registry
|
||||
order, for example `{"npcs":[{"name":"Mira Thorn"}]}`. The projection omits
|
||||
IDs and evidence. Its digest covers the exact projected bytes and is used for
|
||||
consumer-local checkpoint identity, while the full durable artifact digest
|
||||
remains the manifest and generated-reference provenance identity. The unbound
|
||||
projection is exactly `{"npcs":[]}` and also has a projection digest.
|
||||
This registry can ground actor or caster names in the [spell](dnd-spell-artifacts.md)
|
||||
and [combat-turn](dnd-combat-turn-artifacts.md) artifacts. It is required to
|
||||
resolve the canonical `name` in an [NPC interaction](dnd-npc-interaction-artifacts.md).
|
||||
The [JSON output contract](json-output.md) defines publication, and
|
||||
[D&D module internals](../internal/dnd.md) owns pipeline mechanics.
|
||||
|
||||
Reference in New Issue
Block a user