16 KiB
Combat Enemy Event Extraction
Purpose
Define a minimal, evidence-grounded D&D artifact that records enemies engaged and their explicitly observed combat outcomes. The artifact is the durable primitive from which an end-of-session encounter ledger can be derived; this scope does not ask an LLM to synthesize a final ledger or infer an outcome from silence.
This roadmap follows ADR-0009: the extractor answers one narrow question, every reported fact has direct transcript evidence, and generated artifacts provide grounding rather than evidence.
Context
Notarius can currently identify NPCs, classify NPC interactions, record combat turns, and classify scenes. Those artifacts answer useful but different questions:
- the NPC registry establishes individually identifiable names;
- NPC interactions identify such occurrences as
combat_opponentbut do not record outcomes; - combat turns establish actors and action boundaries but deliberately omit action contents and state; and
- scene descriptions determine which chunks are combat scenes.
None can establish by itself that an opponent was killed, fled, captured, or incapacitated. Deriving those outcomes from an absent later turn, the end of a scene, or a combat-opponent classification would create unsupported claims. The new extractor therefore reads the combat transcript directly while using the four normalized artifacts above as explicit auxiliary grounding.
Goals
- Produce an ordered list of directly evidenced enemy engagement and outcome events.
- Keep the durable event shape to
name,kind, andsource_refs. - Run the LLM only for chunks with an exact
combatscene classification. - Ground named subjects in the normalized NPC registry and use prior combat artifacts to constrain participation and allegiance without treating them as evidence.
- Support unnamed individuals and groups without inventing synthetic member identities.
- Preserve repeated engagements and state changes rather than collapsing them into one synthesized terminal record.
- Integrate the lane into the maintained complete D&D pipeline as a later ordered step.
- Follow the existing D&D codec, prompt, normalization, validation, registration, evidence-publication, checkpoint, and documentation conventions.
Target End State
Durable Artifact Contract
The new production module key is dnd/enemy-events. Its typed artifact is:
| Property | Value |
|---|---|
| Artifact kind | dnd/enemy-event-list |
| Schema ID | notarius.dnd.enemy_events |
| Schema name | notarius_dnd_enemy_events_v1 |
| Schema version | v1 |
| Media type | application/json |
| Root field | events |
The root is a strict object with one required events array. The array may be
empty. Each event is a strict object with exactly these required fields:
| Field | Contract |
|---|---|
name |
Non-empty display name or directly grounded collective subject label. |
kind |
engaged, killed, fled, captured, or incapacitated. |
source_refs |
One or more inclusive current-transcript evidence ranges. |
Each source reference has exactly source_id, start_unit_id, and
end_unit_id, following the existing generic source-reference contract. The
durable schema rejects unknown fields and incompatible types.
Example:
{
"events": [
{
"name": "Ashfang",
"kind": "engaged",
"source_refs": [
{"source_id": "session-7", "start_unit_id": 41, "end_unit_id": 42}
]
},
{
"name": "Ashfang",
"kind": "fled",
"source_refs": [
{"source_id": "session-7", "start_unit_id": 57, "end_unit_id": 58}
]
}
]
}
The artifact does not contain an NPC ID, scene ID, quantity, confidence, description, rationale, summary, current state, or inferred terminal outcome. Scene membership remains deterministically derivable by intersecting event evidence with scene ranges. Cross-artifact durable NPC IDs remain governed by the separate future identity-link design consideration.
Event Semantics
| Kind | Required evidence |
|---|---|
engaged |
The subject is directly established as actively opposing the party in combat. Emit at most one engagement for the same subject in one combat scene. |
killed |
The transcript explicitly establishes that the subject died or was killed. Damage, defeat, disappearance, or the end of combat is insufficient. |
fled |
The subject explicitly escapes, retreats, or otherwise leaves the combat to avoid continued engagement. Mere movement or absence from later turns is insufficient. |
captured |
The subject is explicitly taken prisoner or secured under the party's control. A grapple or temporary restraint alone is insufficient. |
incapacitated |
The subject is explicitly rendered unable to continue acting without being established as killed or captured. Do not infer this from a missed turn. |
An outcome may share evidence with an engagement, in which case both events are emitted. A later engagement for the same named subject is preserved, even after an earlier outcome, because enemies may escape, recover, return, or be revived. The event list records observations rather than asserting irreversible state transitions.
active and unresolved are not model-produced event kinds. A downstream
ledger may report the most recent explicit outcome for a subject and use
unresolved when an engagement has no later evidenced outcome. It must not use
active merely because no terminal event was extracted. A distinct future
contract would be required if operators need an evidenced ongoing-combat state.
Subject Identity And Groups
- An individually named subject that matches the normalized NPC registry uses the registry's canonical display name.
- A hostile creature or summoned entity is included when it directly opposes the party, whether or not it has an NPC-registry entry.
- An unnamed homogeneous group is represented collectively with the narrowest
transcript-grounded label, such as
Orcs. The extractor does not inventOrc 1,Orc 2, or other synthetic identities. - When evidence applies only to a subgroup or one unidentified member, use the
narrowest supported phrase, such as
One orcorRemaining orcs. Do not claim a deterministic identity link between that phrase and another group event. - Named subjects may be compared across scenes through the canonical NPC name. Generic or collective subjects are scoped to their combat scene by their evidence range and are not assumed to be the same group in another scene.
- Party members, combat allies, neutral observers, mentioned-but-absent enemies, hazards, traps, and environmental effects are excluded. Uncertain allegiance is not enough to emit an event.
These conservative rules prefer separate, explicitly evidenced observations over a falsely precise encounter roster.
Ordered Pipeline And References
The extractor is an LLM-backed lane in a third maintained D&D pipeline step. It requires four JSON artifact reference slots at extraction:
| Slot | Artifact kind | Purpose |
|---|---|---|
npcs |
dnd/npc-list |
Canonical grounding for individually named subjects. |
scene_descriptions |
dnd/scene-description-list |
Eligibility gate for exact combat scenes. |
combat_turns |
dnd/combat-turn-list |
Grounding for observed combat actors and action boundaries. |
npc_interactions |
dnd/npc-interaction-list |
Grounding for named combat_opponent occurrences. |
Each slot is required, accepts application/json, accepts only its listed
artifact kind, and has a 1,048,576-byte limit consistent with the current D&D
registry references. The framework may satisfy the contract with a compatible
external artifact, but the maintained complete pipeline uses generated
references from earlier steps.
The deterministic normalizer requires only the npcs slot. The other three
artifacts inform extraction and scene routing but do not participate in final
name canonicalization.
The maintained complete pipeline has this topology:
describe-session
-> npcs
-> scene-descriptions
extract-events
-> combat-turns
-> npc-interactions
track-enemies
-> enemy-events
track-enemies consumes npcs and scene-descriptions from
describe-session, and combat-turns and npc-interactions from
extract-events. An invalid, rejected, absent, ambiguous, or incompatible
upstream generated artifact prevents the dependent step from starting under
the existing single-run failure semantics. No new DAG or workflow mechanism is
introduced.
Eligibility And Grounding Projections
The extractor reuses the scene-description registry's exact chunk matching:
- exact
combatmatch: prepare grounding inputs and call the LLM; - exact non-combat match: return an accepted non-nil empty event list without an LLM call; and
- missing or mismatched classification: return an accepted non-nil empty event
list with the bounded
scene_classification_unavailablewarning and no LLM call.
Auxiliary artifacts are decoded and projected into compact, canonical prompt inputs:
- NPCs retain only canonical
namevalues; - combat turns retain only
actorandturn_kind; - NPC interactions retain only
nameandkind, and onlycombat_opponentrecords are included; and - scene descriptions are used only for eligibility and are not rendered into the extraction prompt.
All artifact IDs, source references, summaries, producer provenance, and origin URIs are excluded from the projections. Projection content receives its own digest. Full generated-reference content and producer provenance continue to participate in the framework's existing handoff and checkpoint identity. Neither a projection nor its source references may be copied into event evidence.
Prompt And Private Response Contract
The extractor uses prompt ID dnd.enemy_events, PromptKit default profile
dnd-extraction, and a strict private response schema named
notarius_dnd_enemy_events_llm_v1. The private schema contains required
name, kind, and segment-range candidates; deterministic mapping attaches
the current source ID and preserves semantic candidates for validators.
Prompt construction follows the shared D&D extraction convention. The first four rendered messages remain exactly the shared system, identity, campaign reference, and chunk-transcript messages in their existing cache-control arrangement. Evidence policy, the NPC registry, module-owned compact combat grounding, task, and final instructions follow the transcript. The new module reuses shared assets instead of copying their text, and its final instructions message carries ephemeral cache control.
The prompt makes clear that grounding artifacts are hints, not proof; the current combat transcript is the only evidence; every event requires its own chunk-confined ranges; and absence from a turn list or opponent list does not establish an outcome.
Deterministic Normalization
dnd/enemy-events also identifies a deterministic normalizer for the same
typed artifact. It:
- clones caller-owned data;
- collapses display whitespace in every subject name;
- replaces a recognized subject with the canonical NPC-registry display name, while retaining normalized unmatched group labels;
- canonically orders and removes exact duplicate source ranges;
- orders events by earliest valid source position, then normalized comparison
name, display name, the explicit kind order
engaged,incapacitated,captured,fled,killed, and complete reference sequence; invalid evidence sorts after valid evidence for deterministic validation; and - collapses only records with the same normalized subject identity, kind, and complete canonical evidence sequence, retaining the earliest display value.
Distinct event kinds, distinct evidence, repeated engagements in different scenes, and later outcome changes remain separate. Normalization never manufactures an engagement or outcome and never aggregates the list into a ledger. It is idempotent and emits bounded warnings for name changes, evidence normalization, reordering, and exact duplicate collapse.
Validation And Production Policy
The D&D registrar provides these validators:
extract/dnd/enemy-events/shape;extract/dnd/enemy-events/engagements;extract/dnd/enemy-events/source_refs;extract/dnd/enemy-events/source_relatedness; andnormalize/dnd/enemy-events/invariants.
The extraction default chain is:
generic/valid_json
extract/dnd/enemy-events/shape
extract/dnd/enemy-events/engagements
extract/dnd/enemy-events/source_refs
generic/valid_json_schema
extract/dnd/enemy-events/source_relatedness
The normalization default chain inserts
normalize/dnd/enemy-events/invariants after the shape validator. Shape owns
non-empty names, the closed event-kind vocabulary, and non-empty evidence.
Source-reference validation owns current-document range validity. Durable
schema validation owns the public JSON shape. Relatedness remains advisory.
The invariant validator owns canonical display values, registry-aware
canonical names where applicable, canonical evidence, deterministic ordering,
and absence of exact duplicates.
No production LLM-backed validator is added. Semantic quality should first be evaluated through the extractor prompt and human review rather than adding a second model judgment without a concrete policy.
The registrar also supplies the strict codec, typed append-order merger, deterministic normalizer, typed no-op normalizer compatibility, typed evidence projection, prompt and schema assets, safe manifest metadata, and stable checkpoint fingerprints. Operation-varying generated reference content stays in framework-owned reference/checkpoint identity rather than static module metadata.
Output, Examples, And Documentation
The JSON output encoder publishes normalized enemy events like every other
typed lane. The maintained complete example adds enemy-events to its evidence
context allowlist and demonstrates the third generated-reference step. The
minimal example remains unchanged.
When implemented, canonical documentation adds a D&D enemy-event integration
contract, adds the production keys, slots, and default chains to
docs/config.md, and updates docs/internal/dnd.md for the seventh lane,
grounding projections, prompt ordering, eligibility, and normalization.
Current-behavior documents do not describe the feature before its code lands.
Out Of Scope
- A separately published aggregated enemy-ledger artifact or inventory-like state store.
- Model-produced
active,unresolved, confidence, rationale, description, or summary fields. - Synthetic identities or quantities for indistinguishable enemies.
- Durable NPC-ID links, alias resolution beyond the normalized registry, or a general cross-artifact entity graph.
- Inferring outcomes from turn absence, scene termination, hit-point guesses, initiative order, or other artifacts.
- Deriving enemy events solely from combat turns or NPC interactions.
- Changing existing combat-turn, NPC, NPC-interaction, or scene-description schemas.
- A general workflow DAG, general reference-query system, or generic semantic deduplication framework.
- Paid or live-model tests in the default suite.
Acceptance Criteria
dnd/enemy-eventsproduces the strict minimalv1event artifact and preserves direct transcript evidence for every record.- Only exact combat scenes invoke the LLM; non-combat and unclassified chunks follow the defined empty-result behavior.
- The extractor consumes validated NPC, scene-description, combat-turn, and NPC-interaction references through source-free grounding projections.
- Named enemies canonicalize through the NPC registry while unmatched individuals and collective labels remain supported without invented IDs.
- The normalizer is deterministic, idempotent, ownership-safe, warning-bounded, and collapses exact duplicates only.
- The codec, validators, default chains, merger, no-op compatibility, evidence projector, prompt assets, fingerprints, and module specs are registered by the D&D family.
- The maintained complete pipeline resolves and runs the new third step with compatible generated references from both earlier steps.
- Canonical documentation and maintained examples describe only implemented behavior, remain secret-free, and pass their existing offline contract tests.