Finalize D&D prompt integration and documentation

This commit is contained in:
2026-07-21 14:58:26 +00:00
parent b344d16dc1
commit 3ba2bfd7f6
8 changed files with 105 additions and 236 deletions

View File

@@ -98,30 +98,36 @@ D&D prompt content. `internal/framework/promptfs` provides the domain-neutral
filesystem composition helper used to combine module-owned files with shared
domain prompt fragments.
The D&D spell, NPC, and combat-turn extractors each declare an ordered prompt
asset manifest. The manifest lists the package-owned YAML and Markdown files,
then the exact shared fragments rendered by that prompt; the same ordered list
drives both filesystem mounting and the prompt fingerprint. Shared extraction
evidence and in-world identity messages precede the cacheable transcript and
campaign-reference messages. Spell and combat prompts then render immediate
resolution and the cacheable NPC registry before their lane-specific material;
the NPC prompt renders its task and instructions instead. The identity,
transcript, and campaign-reference messages are ephemeral in all three prompts,
and the NPC registry is ephemeral where it is used by spell and combat prompts.
Unused shared assets are neither mounted nor fingerprinted.
The D&D scene chunker and spell, NPC, and combat-turn extractors each declare an
ordered prompt asset manifest. The manifest lists the package-owned YAML and
Markdown files, then the exact shared fragments rendered by that prompt; the
same ordered list drives both filesystem mounting and the prompt fingerprint.
The three extraction prompts share system, extraction evidence, in-world
identity, transcript, and campaign-reference messages. Spell and combat prompts
then render immediate resolution and the ephemeral NPC registry before their
lane-specific material; the NPC prompt renders its task and instructions
instead. The scene prompt uses system, transcript, and campaign-reference
messages before its task and instructions. Identity, transcript, and
campaign-reference messages are ephemeral in the extraction prompts; the scene
prompt marks transcript and campaign references ephemeral, and the NPC registry
is ephemeral where spell and combat prompts use it. Unused shared assets are
neither mounted nor fingerprinted.
Schema helpers load embedded JSON Schema with identity and digest metadata,
return defensive copies, and expose a diagnostics map that omits schema bytes.
The small framework registry contains only generic test schemas; production
schemas remain package-owned.
The spell and combat extractors' package-owned prompts declare their structured
JSON inputs and private response schemas. The combat private schema owns the
transport envelope—required fields, JSON types, nullability, and unknown-field
rejection—while its deterministic validators own semantic constraints such as
enum membership, non-empty values and collections, and positive numbers. The
spell extractor's prompt declares a required `application/json` `spell_catalog`
input and an optional `application/json` `npcs` input. The extractor generates
The spell, NPC, and combat extractors' package-owned prompts declare their
structured JSON inputs and private response schemas. Each private response
schema remains separate from its durable artifact codec schema; this work does
not use shared schema fragments or schema generation. The combat private schema
owns the transport envelope—required fields, JSON types, nullability, and
unknown-field rejection—while its deterministic validators own semantic
constraints such as enum membership, non-empty values and collections, and
positive numbers. The spell extractor's prompt declares a required
`application/json` `spell_catalog` input and an optional `application/json`
`npcs` input. The extractor generates
the catalog input from its prepared
effective catalog as `{"spell_names":[...]}` using sorted canonical names only.
The shared D&D prompt assets include a generic NPC grounding fragment directly

View File

@@ -48,15 +48,18 @@ package-local embedded assets. Shared filesystem composition belongs in
`internal/framework/promptfs`; reusable D&D prompt fragments, reference
declarations, prompt-input assembly, and source-unit/citation helpers belong in
`internal/modules/dnd/shared`, which also owns bounded D&D diagnostics. The
spell, NPC, and combat-turn extractors use ordered package-local prompt
manifests for both rendering and prompt fingerprinting, so only the shared
fragments each prompt actually renders participate in either operation. Their
common prompt order is system, extraction evidence, in-world identity,
transcript, and campaign references, with ephemeral cache control on identity,
transcript, and references. Spell and combat prompts append immediate
resolution and an ephemeral NPC registry before lane-specific material; the
NPC prompt appends its task and instructions. Stage contracts expose only
Notarius structured-completion types, not Scriptorium public types.
D&D scene chunker and spell, NPC, and combat-turn extractors use ordered
package-local prompt manifests for both rendering and prompt fingerprinting, so
only the shared fragments each prompt actually renders participate in either
operation. The three extraction prompts share the order system, extraction
evidence, in-world identity, transcript, and campaign references, with
ephemeral cache control on identity, transcript, and references. Spell and
combat prompts append immediate resolution and an ephemeral NPC registry before
lane-specific material; the NPC prompt appends its task and instructions. The
scene prompt uses system, transcript, and campaign references before its
lane-specific task and instructions, with ephemeral cache control on transcript
and references. Stage contracts expose only Notarius structured-completion
types, not Scriptorium public types.
The shared `ChunkPromptMaterial` helper owns common transcript material
preparation for the spell, NPC, and combat-turn extractors. It clones supplied
@@ -361,8 +364,9 @@ reject the complete result with bounded, stable index/name diagnostics. The
source-reference validator defers malformed shapes, validates every cited
range, and reports all range defects through a bounded aggregate while
preserving `invalid_source_refs`. The relatedness validator resolves all cited
ranges through the shared document-order traversal, then warns when a
case-insensitive spell name is absent from the cited source text. Invalid shape
ranges through the shared document-order traversal, then warns when a normalized
consecutive spell-name token sequence is absent from the cited source text.
Invalid shape
or cited ranges produce no relatedness warnings; the shape and source-reference
validators own those defects.
@@ -416,7 +420,9 @@ that order, then exposes the matching catalog for resolution. The generic and
Seriatim registrars own their production leaf registrations. The D&D registrar
owns D&D leaf registrations, typed spell, NPC, and combat default-validator
chains, typed append-order specializations, and D&D prompt/schema asset
collection.
collection. Its registration helpers group module, validator, prompt-asset, and
chain composition while retaining artifact-specific merge and clone behavior in
the registrar.
Concrete implementation packages do not import generic implementation
packages directly. A concrete family's `register` package is its composition

View File

@@ -1,180 +1,35 @@
# D&D Module Harmonization And Prompt Reuse
This roadmap records proposed improvements to the spell, NPC, and combat-turn
pipeline lanes. Current implemented behavior remains documented in the
[module internals](../internal/modules.md) and
[LLM runtime internals](../internal/llm.md). The work below is not yet an
implemented contract.
This roadmap tracked harmonization of the spell, NPC, and combat-turn lanes.
The implemented behavior is now owned by [Module Internals](../internal/modules.md)
and [LLM Runtime Internals](../internal/llm.md); this document records status
and the one remaining external prerequisite rather than duplicating those
current-behavior references.
The three lanes already share the same overall decomposition: a typed
extractor, durable codec, merger, normalizer, shape and provenance validators,
domain-specific validation, embedded prompt assets, and central production
registration. Spell catalog resolution, NPC identity and registry support, and
combat normalization invariants are intentional domain differences. The goal
is to remove mechanical drift without hiding those differences behind a broad
generic abstraction.
## Implementation Status
## Target State
The offline/runtime work is complete:
### Prompt Reuse Is A Rendered-Request Invariant
- shared prompt assets have explicit per-prompt manifests that drive both
mounting and prompt fingerprints;
- shared prompt inputs, deterministic chunk material preparation, and cited
source traversal are centralized;
- prompt ordering and cache-control policy are aligned across the D&D
extraction prompts, while scene chunking retains its distinct prompt shape;
- validator prerequisite, bounded-diagnostic, and checkpoint policies are
aligned without changing compatibility-sensitive identifiers;
- production registration remains explicit and typed, with grouped composition,
central default-chain ownership, and artifact-specific merge behavior;
- private LLM response schemas remain package-owned and separate from durable
codec schemas; and
- focused tests and repository-wide test, vet, build, and diff checks pass.
Provider prompt caching depends on the request prefix being byte-for-byte
identical. Similar prose, duplicated files, or equivalent structured values are
not sufficient. Treat message role, content bytes, ordering, cache-control
metadata, input rendering, and any provider-visible separators as part of the
cache identity.
## Deferred evaluation
The target prompt layout has the longest valid common prefix before any
module-specific message:
- Put shared static system, extraction-evidence, and in-world-identity policy
before dynamic transcript and campaign-reference messages so reuse does not
depend on identical transcript content.
- Keep the shared transcript and campaign-reference messages in the same roles
and order in every D&D extractor.
- Keep cache-control declarations identical on corresponding messages.
- Define one canonical ordering and serialization for shared named inputs.
Continue resolving the deprecated `roster` input into the canonical `party`
input before prompt rendering.
- Keep genuinely universal extraction rules in shared message assets. These
rules include using only transcript units as evidence, treating references as
disambiguation, returning schema-conforming JSON only, using integer
`start_unit_id` and `end_unit_id` values, omitting `source_id` for the mapper
to assign, citing all factual claims, and preferring narrow ranges over broad
ranges that bridge unrelated conversation.
- Use one shared in-world identity message for lanes whose artifacts name
actors or participants. It contains only rules that spells, NPCs, and combat
turns can follow verbatim; artifact-specific identity, alias, target, and
relationship rules remain local.
- Keep rules shared by only a subset in subset-specific shared assets. The
immediate-declaration-and-resolution boundary and NPC-registry grounding are
shared by spells and combat. The NPC extractor does not consume a prior NPC
registry.
- Place subset-specific and module-specific messages only after the longest
useful all-lane prefix. Place schema-specific task instructions last.
- Avoid inserting a nominally shared message when its rendered input or
wording differs by lane. Factor the common bytes into one message and leave
the differences in later messages instead.
Shared messages are embedded once and referenced by every applicable prompt.
This makes reuse of the canonical asset the easiest way to preserve cache
identity and avoids parallel module-specific copies that can drift.
### Shared Prompt Ownership And Input Behavior Are Protected
Focused tests protect shared asset composition and input behavior without
snapshotting the length or exact boundary of the common message prefix.
- Verify that each applicable prompt mounts and renders the canonical shared
assets rather than module-specific copies.
- Verify common input material identity, including name, media type, content,
digest, origin URI, size, empty-value representation, reference ordering,
and `roster` fallback behavior.
- Test that every prompt fingerprint includes exactly the assets actually
rendered by that prompt. The current grouped reference hash helper should be
replaced or refined so a module does not fingerprint an unused shared asset,
while no used asset is omitted.
- Document the expected shared message ordering and cache-control policy so
later changes are reviewed against the caching intent.
- Prefer behavioral and ownership assertions over message-count, prefix-length,
or full-prompt snapshots.
### Stable Extraction Preparation Is Centralized
Move the three identical chunk-input preparation implementations into a D&D
shared helper. The helper should clone the supplied material, fall back to the
chunk content, verify byte equality, and fill the canonical name, media type,
and size without retaining mutable request data.
Nil context, cancellation, source, chunk, and empty-unit checks remain local so
typed result handling and module error context stay explicit. Do not wrap the
complete LLM call, response DTO mapping, catalog preparation, registry
preparation, or manifest metadata in a generic extractor framework.
Use the shared helper as the single source of the `transcript` prompt material
so identical input requests cannot drift between lanes.
### Validator Checkpoint And Composition Policy Is Aligned
- Add explicit versioned policy checkpoint fingerprints to the spell shape,
source-reference, and source-relatedness validators. Bump a policy version
whenever acceptance, rejection, warning, or diagnostic-selection behavior
changes.
- Shape validators own malformed artifact shape; later validators defer when
shape is invalid.
- Make all source-reference validators collect bounded diagnostics through the
shared D&D diagnostics package rather than mixing first-error and aggregate
behavior.
- Use artifact-qualified reason codes consistently unless a reason code is
intentionally a stable cross-artifact contract.
- Add a compact cross-lane validator contract test covering deterministic
execution class, strict empty options, registration, policy fingerprinting,
prerequisite behavior, and diagnostic bounds.
### Source-Evidence Traversal Is Shared
Extract a D&D helper that validates source ranges and returns cited units or
text once, in source-document order, without repeating units covered by
overlapping ranges. Use it from spell, NPC, and combat relatedness validators.
Keep matching policy artifact-specific:
- spell matching may use canonical catalog names and aliases;
- NPC matching may use NPC comparison keys and aliases; and
- combat matching may apply separate actor and declaration heuristics.
Review Unicode normalization, apostrophe handling, word boundaries, short-name
false positives, multiword identities, and overlapping ranges with shared
table-driven fixtures. Relatedness remains a warning heuristic and should not
be presented as proof that every semantic claim is supported.
## Structural Cleanup
### Lane Registration
Reduce repetition in the central D&D registrar with focused registration
helpers grouped by modules, validators, prompt assets, and default chains.
Retain artifact-specific append and deep-clone behavior in the registrar,
central ownership of validator ordering, and explicit typed registration.
Avoid reflection and heterogeneous erased lane descriptors.
### Naming And Package Conventions
Adopt consistent conventions for package aliases, module keys, artifact kinds,
prompt IDs, schema IDs, reason codes, policy IDs, metadata fields, and
checkpoint fingerprint names. Compatibility-sensitive identifiers should
change only through an explicit migration; internal aliases can be harmonized
independently.
### Schemas And Assets
- Keep private LLM response schemas distinct from durable artifact codec
schemas. They represent different trust and compatibility boundaries.
- Keep source-reference schema definitions package-owned in this work; do not
add schema composition or generation machinery solely to deduplicate them.
- Prefer one embedded shared asset over synchronized copies whenever content
must be identical for prompt caching.
- Make prompt fingerprints derive from an explicit prompt asset manifest, or
from the prepared prompt definition, so message composition and provenance
cannot drift independently.
Prompt factoring must not be accepted solely because cache reuse improves.
Retain or restore module-specific wording when evaluation shows a meaningful
quality regression. Record cache observations using non-secret request and
usage metadata rather than prompt or transcript payloads.
## Completion Criteria
This roadmap is complete when:
- the three lanes expose the same stable structural conventions while keeping
documented domain differences local;
- shared provider-visible messages are produced from canonical shared assets,
and shared inputs have one deterministic implementation;
- the common prompt ordering is deliberate, documented, and as cache-friendly
as extraction quality permits;
- every validator policy that affects reusable results participates in
checkpoint identity;
- source-reference traversal and diagnostics no longer drift between lanes;
- registration remains explicit and type-safe; and
- focused D&D tests plus repository-wide tests, vetting, and the CLI build pass.
An optional live before/after provider comparison remains deferred because it
requires credentials and a maintained human-reviewed transcript or fixture
set. It is not part of the default test suite or merge gate. If those
prerequisites become available, record only aggregate extraction-review
results, prompt token counts, cache-hit/cache-write metrics, and non-secret
prompt hashes. Never commit transcript content, rendered prompts, credentials,
endpoints, or private reference material.