Harmonize D&D artifact contracts
This commit is contained in:
@@ -1,133 +1,78 @@
|
||||
# D&D Item-Event Artifact Contract
|
||||
# D&D Item-Event Artifact
|
||||
|
||||
This document defines the durable D&D item-event artifact and its production
|
||||
boundaries. It records source-grounded discoveries and possession changes; it
|
||||
does not maintain an inventory or ledger.
|
||||
This contract defines the durable item and currency occurrence list produced by
|
||||
`dnd/item-events`. It records source-grounded discoveries and possession
|
||||
changes; it does not maintain an inventory, balance, or ledger.
|
||||
|
||||
## Artifact Identity
|
||||
## Identity and compatibility
|
||||
|
||||
| Property | Value |
|
||||
| --- | --- |
|
||||
| Extractor key | `dnd/item-events` |
|
||||
| Extract capability | `dnd.item_events` |
|
||||
| Artifact kind | `dnd/item-event-list` |
|
||||
| Schema ID | `notarius.dnd.item_events` |
|
||||
| Schema name | `notarius_dnd_item_events_v1` |
|
||||
| Schema version | `v1` |
|
||||
| Media type | `application/json` |
|
||||
| Normalizer key | `dnd/item-events` |
|
||||
|
||||
The payload is one strict JSON object containing a required `events` array,
|
||||
which may be empty. Objects reject unknown fields.
|
||||
`v1` is a strict JSON object with required `events`; the array may be empty.
|
||||
Event and source-reference objects reject unknown fields. A future incompatible
|
||||
shape requires a new schema version.
|
||||
|
||||
## Event Shape And Categories
|
||||
## Wire shape
|
||||
|
||||
Every event has `name`, `kind`, and a non-empty `source_refs` array. `quantity`
|
||||
is optional and, when present, is a positive integer. `from` and `to` are
|
||||
optional display values whose presence depends on `kind`.
|
||||
Every event has required `name`, `kind`, and `source_refs`. `quantity`, `from`,
|
||||
and `to` are optional where the event kind permits them.
|
||||
|
||||
| Field | Rule |
|
||||
| Field | Contract |
|
||||
| --- | --- |
|
||||
| `name` | Non-empty, transcript-supported display value. |
|
||||
| `kind` | One of the categories below. |
|
||||
| `quantity` | Optional positive integer; omitted when the source does not establish a count. |
|
||||
| `from` | Holder that loses possession when the category permits it. |
|
||||
| `to` | Holder that gains possession when the category permits it. |
|
||||
| `source_refs` | One or more current-source references. |
|
||||
| `name` | Non-empty item or currency display name. |
|
||||
| `kind` | `discovered`, `acquired`, `lost`, `consumed`, or `transferred`. |
|
||||
| `quantity` | Optional positive integer; omit it when no count is established. |
|
||||
| `from` | Optional non-empty losing holder, when allowed by `kind`. |
|
||||
| `to` | Optional non-empty gaining holder, when allowed by `kind`. |
|
||||
| `source_refs` | One or more transcript evidence ranges. |
|
||||
|
||||
| Kind | Meaning and holder rule |
|
||||
| --- | --- |
|
||||
| `discovered` | The party learns of or encounters an item without established possession; neither holder is present. |
|
||||
| `acquired` | A party member or `party` gains possession; `to` is required and `from` is absent. |
|
||||
| `lost` | A party member or `party` ceases to possess an item without consuming it; `from` is required and `to` is absent. |
|
||||
| `consumed` | Use depletes, expends, or destroys an item; `from` is required and `to` is absent. |
|
||||
| `transferred` | Possession moves between distinct party members; both holders are required and neither may be `party`. |
|
||||
|
||||
`party` is the reserved display holder for collective party possession when an
|
||||
individual holder is not established. Its comparison is case- and
|
||||
Unicode-insensitive. Transfers require distinct normalized holder values.
|
||||
Giving an item to an NPC, spending currency, selling an item, or another move
|
||||
outside party possession is `lost`, not `transferred` or `consumed`. Monetary
|
||||
spending, purchases, and payments are always `lost`. Currency is `consumed` only
|
||||
when the source explicitly describes its physical destruction or expenditure as
|
||||
a non-payment component. Ordinary non-depleting use is not an event.
|
||||
|
||||
Currency is represented as an ordinary event name plus an explicit quantity
|
||||
when the transcript supplies one. Each denomination remains separate. The
|
||||
artifact never converts denominations, infers a missing count, calculates a
|
||||
balance, or sums nearby events.
|
||||
|
||||
## Source Evidence And Normalization
|
||||
|
||||
Each source reference contains `source_id`, `start_unit_id`, and `end_unit_id`.
|
||||
It must identify an ordered range in the current source document. During
|
||||
extraction, every cited range must also be wholly contained in the current
|
||||
accepted chunk. Campaign references may disambiguate names, but never provide
|
||||
event evidence.
|
||||
|
||||
The deterministic normalizer trims only display-edge whitespace in names and
|
||||
holders, canonicalizes source-reference order and exact duplicate references,
|
||||
then orders events by earliest valid source position and stable tie-breakers
|
||||
over name, kind, holders, quantity, and complete evidence. It removes only
|
||||
events with the same normalized fields and complete valid evidence sequence.
|
||||
Invalid evidence is never collapsed. It does not rename, singularize, resolve
|
||||
aliases, infer holders or quantities, or merge nearby events.
|
||||
|
||||
The default extraction validation chain is JSON syntax, item-event shape,
|
||||
source references, durable JSON Schema, then advisory source relatedness. The
|
||||
normalization chain adds normalized invariants after shape validation and before
|
||||
source references and schema validation. Relatedness warnings are advisory so
|
||||
contextual names and currency notation do not reject otherwise valid evidence.
|
||||
|
||||
## Representative JSON
|
||||
Each source reference has exactly `source_id`, `start_unit_id`, and
|
||||
`end_unit_id`. It identifies an inclusive current-transcript range; unit IDs
|
||||
are positive and the start may not follow the end.
|
||||
|
||||
```json
|
||||
{
|
||||
"events": [
|
||||
{
|
||||
"name": "Hidden Cache",
|
||||
"kind": "discovered",
|
||||
"source_refs": [{"source_id": "session-7", "start_unit_id": 1, "end_unit_id": 1}]
|
||||
},
|
||||
{
|
||||
"name": "Silver Pieces",
|
||||
"kind": "acquired",
|
||||
"quantity": 20,
|
||||
"to": "party",
|
||||
"source_refs": [{"source_id": "session-7", "start_unit_id": 2, "end_unit_id": 2}]
|
||||
},
|
||||
{
|
||||
"name": "Torch",
|
||||
"kind": "lost",
|
||||
"from": "party",
|
||||
"source_refs": [{"source_id": "session-7", "start_unit_id": 3, "end_unit_id": 3}]
|
||||
},
|
||||
{
|
||||
"name": "Healing Potion",
|
||||
"kind": "consumed",
|
||||
"from": "Aria",
|
||||
"source_refs": [{"source_id": "session-7", "start_unit_id": 4, "end_unit_id": 4}]
|
||||
},
|
||||
{
|
||||
"name": "Moonblade",
|
||||
"kind": "transferred",
|
||||
"from": "Aria",
|
||||
"to": "Borin",
|
||||
"source_refs": [{"source_id": "session-7", "start_unit_id": 5, "end_unit_id": 5}]
|
||||
"source_refs": [
|
||||
{"source_id": "session-7", "start_unit_id": 2, "end_unit_id": 2}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Production Boundary
|
||||
## Holder rules and minimal extraction
|
||||
|
||||
The extractor requires `chunks` and `source.transcript`, and accepts optional
|
||||
`glossary`, `party`, `players`, and deprecated `roster` campaign references for
|
||||
disambiguation only. It has no generated NPC, scene-description, or item-registry
|
||||
dependency. The append-order merger preserves chunk order, and the normalizer
|
||||
has no reference slots.
|
||||
`discovered` has neither holder; `acquired` requires `to` and forbids `from`;
|
||||
`lost` and `consumed` require `from` and forbid `to`; `transferred` requires
|
||||
both holders. `party` denotes collective possession. A transfer cannot use
|
||||
`party` for either holder and its two normalized holders must differ.
|
||||
|
||||
The normalized lane is emitted as `lanes/<lane-id>.json` by the JSON output
|
||||
module. See [Configuration](../config.md#implemented-production-modules) for
|
||||
the selectable keys and default chains, and the
|
||||
[JSON output contract](json-output.md) for bundle paths.
|
||||
Only an evidenced discovery or possession change belongs in this artifact.
|
||||
It does not infer quantities or holders, convert currency denominations,
|
||||
calculate balances, or merge nearby events. Campaign references may
|
||||
disambiguate names but are never event evidence. Currency uses the ordinary
|
||||
`name` field and an explicit `quantity` only when the transcript establishes
|
||||
one; each denomination remains a separate event.
|
||||
|
||||
Normalization trims display whitespace, orders and removes exact duplicate
|
||||
source references, then orders events by valid source chronology, name identity
|
||||
and display value, kind, holders, quantity, and reference sequence. It
|
||||
collapses only entries with the same normalized durable fields and complete
|
||||
valid evidence.
|
||||
|
||||
The [JSON output contract](json-output.md) defines publication. See
|
||||
[D&D module internals](../internal/dnd.md) for implementation details and the
|
||||
[NPC-interaction artifact](dnd-npc-interaction-artifacts.md) for a distinct
|
||||
kind of occurrence.
|
||||
|
||||
Reference in New Issue
Block a user