# D&D Prompt Asset Cleanup Implementation Plan ## Objective Implement the target state defined in [D&D Prompt Asset Cleanup](prompts.md): standardize D&D prompt asset names, clarify transcript scopes, consolidate fixed module instructions, remove prompt prose duplication, normalize the two outlying private response-schema identities, and document the resulting authoring conventions. This plan changes internal LLM-facing assets and their owning registration code. It does not change durable artifact contracts, public prompt IDs, module IDs, pipeline configuration, reference bindings, profile selection, or extraction policy. In particular, the proposed registry/occurrence module renaming and the proper-name-only location policy in [Future Work](future.md) are not part of this implementation. The stages are ordered dependencies. Complete and validate each stage before starting the next. Each stage is sized for one gpt-5.6-terra implementation prompt. ## Implementation Rules Apply these rules throughout all stages: - Read `docs/policy/architecture.md`, `docs/policy/documentation.md`, and `docs/policy/testing.md` before making changes. - Keep the root `assets` Go package content-only. Do not add prompt composition, schema selection, registration, or D&D policy to that package. - Preserve every public PromptKit prompt `id`, prompt version, default profile, input name, input requirement, output format, validation mode, and repair setting unless a stage below expressly changes private schema identity. - Preserve the message orders and cache boundaries specified in `prompts.md`. Consolidating fixed prose is not authorization to move variable material or family-specific policy into the system message. - Treat prompt prose as an owned contract, not as text to concatenate mechanically. Merge `task.md` and `instructions.md` by editing the result into one coherent `instructions.md`, removing duplicated transitions and rules. - Begin with minimal, non-repetitive prose. Do not retain or reintroduce a duplicated instruction merely because repetition might help a model. That decision requires later observational evidence. - Preserve all lane-specific domain semantics identified in `prompts.md`, even when removing generic output, evidence, reference, or schema restatements. - Keep all shared filenames prefixed with `common-dnd-`. - Do not add compatibility aliases for retired private asset names or private schema identities. Notarius is pre-release, and one-time prompt fingerprint, checkpoint, and provider-cache invalidation is accepted. - Keep default tests deterministic, offline, and credential-free. Do not call a live LLM during implementation or make live model quality an automated gate. - Do not add exact prompt snapshots, exact shared-prefix lengths, or tests that enumerate every private asset merely to detect change. Retain tests of actual preparation, input placement, cache boundaries, schema registration, and the byte-identical extraction prefix. ## Stage 1: Establish Shared System And Transcript-Scope Assets ### Goal Give universal instructions and each form of transcript material one correct shared owner, then migrate every current D&D prompt to the appropriate scope in one coherent change. ### Required changes 1. Revise `assets/dnd/shared/prompts/common-dnd-system.md` so it contains all and only behavior applicable to scene chunking, every extraction lane, and both entity normalizers: - the D&D transcript-processing role; - reliance only on supplied inputs; - awareness of transcription errors, repetition, incomplete sentences, and misheard proper nouns; and - exactly one schema-conforming JSON object with no explanatory prose. Refer to supplied inputs generally. Do not limit the statement to transcript and reference inputs, because grounded extractors and normalizers receive other material. Do not place rendered inputs, transcript-evidence mechanics, identity policy, reference policy, registry policy, or reconciliation policy in the system message. 2. Revise `assets/dnd/shared/prompts/common-dnd-extraction-evidence.md` to own only extraction evidence and source-range policy. Retain transcript-only evidence, integer range endpoints, omission of `source_id`, and narrow non-contiguous ranges. Remove the universal JSON-only/output-schema sentences now owned by the system message. Avoid repeating detailed campaign-reference or registry semantics owned by their input fragments. 3. Replace `assets/dnd/shared/prompts/common-dnd-transcript.md` with: - `common-dnd-transcript-full.md`, which renders the complete ordered session for scene chunking and does not imply that the complete session is one scene; - `common-dnd-transcript-chunk.md`, which renders one extraction chunk, limits reporting and inference to that chunk, and states that unit IDs retain source-wide meaning; and - `common-dnd-transcript-windows.md`, which renders selected normalization evidence windows and states that they may be incomplete, non-contiguous, or overlapping and that absence outside them is not evidence. Each file must render `{{ input "transcript" }}` exactly once. Scope files describe material completeness and permissible use; do not move scene, extraction-evidence, or reconciliation policy into them. 4. Update `internal/modules/dnd/shared/assets.go` so `sharedPromptPaths` exposes the three new names and no longer exposes `common-dnd-transcript.md`. 5. Update every owning `promptAssetManifest` and current prompt YAML definition to select exactly one transcript-scope asset: | Scope asset | Prompt IDs | | --- | --- | | `common-dnd-transcript-full.md` | `dnd.scenes` | | `common-dnd-transcript-chunk.md` | `dnd.spells`, `dnd.npcs`, `dnd.combat_turns`, `dnd.enemy_events`, `dnd.item_events`, `dnd.npc_interactions`, `dnd.scene_descriptions`, `dnd.locations`, `dnd.location_occurrences` | | `common-dnd-transcript-windows.md` | `dnd.npcs.normalize`, `dnd.locations.normalize` | Preserve the existing message position and cache control while changing the referenced scope filename. Extraction prompts must continue to share the same rendered prefix through the chunk transcript. 6. Update focused prompt-asset and shared-asset tests. A focused assertion that an owning prompt family selects its required transcript scope is warranted; do not replace it with exact prose snapshots or a full shared-file inventory. Expand `internal/modules/dnd/register/prompt_cache_test.go` to include the location and location-occurrence extraction prompts in its byte-identical prefix check while retaining the existing other extraction lanes. ### Acceptance criteria - The old `common-dnd-transcript.md` is absent and unreferenced. - Every D&D prompt prepares with exactly the transcript semantics supplied by its caller. - The shared system message is byte-identical across all D&D prompts and contains no variable input. - The extraction-evidence fragment no longer repeats the universal output rule. - Extraction prompts retain a byte-identical rendered prefix through campaign references and the chunk transcript when given identical inputs. - No public prompt, module, durable artifact, or pipeline contract changes. ### Validation ```sh go test ./internal/modules/dnd/shared/... ./internal/modules/dnd/... git diff --check ``` ## Stage 2: Standardize Prompt And Context Filenames ### Goal Make prompt definitions and variable context assets predictable without changing their rendered content or message order. ### Required changes 1. Rename every prompt-ID-derived YAML file below to `prompt.yaml` and update its owning `promptAssetManifest` entry to mount `prompt.yaml` from `prompts/prompt.yaml`: - `assets/dnd/scenes/prompts/` - `assets/dnd/spells/prompts/` - `assets/dnd/npcs/extract/prompts/` - `assets/dnd/npcs/normalize/prompts/` - `assets/dnd/combat-turns/prompts/` - `assets/dnd/enemy-events/prompts/` - `assets/dnd/item-events/prompts/` - `assets/dnd/npc-interactions/prompts/` - `assets/dnd/scene-descriptions/prompts/` - `assets/dnd/locations/extract/prompts/` - `assets/dnd/locations/normalize/prompts/` - `assets/dnd/location-occurrences/prompts/` Leave the YAML `id` fields unchanged. PromptKit continues to distinguish the definitions through each manifest's existing `ModuleDir`. 2. Apply these context-fragment renames and update both YAML `content_file` references and manifest `ModuleFiles` entries: - `assets/dnd/spells/prompts/catalog.md` to `spell-catalog.md`; - `assets/dnd/enemy-events/prompts/grounding.md` to `combat-grounding.md`; and - `assets/dnd/location-occurrences/prompts/locations.md` to `location-registry.md`. Do not edit their prompt prose in this mechanical stage. 3. Update tests that intentionally exercise the production asset layout: - In `internal/modules/dnd/register/register_test.go`, retain a registrar- boundary check for one canonical `prompt.yaml` per maintained prompt, but remove lists of every task, instruction, context, and shared fragment. - In `internal/cli/production_contract_test.go`, remove private prompt-file inventory assertions already owned by the D&D registrar and module prompt- preparation tests. Retain its CLI composition and public catalog contract checks. - Update module-local tests only where a renamed file is intentionally part of the manifest/preparation behavior. - Do not rewrite generic `internal/framework/llm` or `internal/framework/promptfs` fixtures merely because they use arbitrary noncanonical filenames; those tests prove generic filesystem behavior, not the D&D authoring convention. 4. Search for and remove all production references to the retired filenames. Do not preserve copies or aliases. ### Acceptance criteria - Every D&D prompt subtree contains `prompt.yaml` and no prompt-ID-derived YAML definition. - The three renamed context files have descriptive names and render in their original message positions. - Every module manifest mounts the canonical names and still produces a prompt fingerprint. - Production-composition tests protect registration behavior without enumerating every private content file. - All prompts prepare through PromptKit with unchanged IDs, versions, inputs, profiles, output modes, and cache controls. ### Validation ```sh go test ./internal/modules/dnd/... ./internal/cli/... git diff --check ``` ## Stage 3: Consolidate Scene And Entity-Normalization Instructions ### Goal Adopt the single `instructions.md` convention for scene chunking, scene description, NPC normalization, and location normalization while preserving their distinct message-order contracts. ### Required changes 1. For scene chunking, merge `task.md` and `instructions.md` into one coherent `instructions.md` and delete `task.md`. Retain: - the definition of a coherent scene and meaningful boundary conditions; - reasons to split and reasons not to split; - complete ordered transcript coverage with no gaps or overlaps; and - inclusive, positive source-unit endpoints. Remove the generic JSON-only rule now owned by the system prompt and field- exclusivity prose already enforced by the private response schema. In `prompt.yaml`, place the combined instructions after campaign references and before the full transcript. It has no cache control; references and the final full transcript retain ephemeral cache control. 2. For scene descriptions, merge `task.md` and `instructions.md` into one `instructions.md` and delete `task.md`. Retain the one-accepted-chunk scope, all `kind` definitions and precedence, and title and summary semantics. Remove schema field-list exclusions and universal JSON-only language. Keep the combined final instructions message ephemeral. 3. For both NPC and location normalizers, rename `task.md` to `instructions.md`, update `prompt.yaml` and the manifest, and edit the prose against `common-dnd-entity-reconciliation.md`: - NPC instructions own same-individual alias judgment and canonical display- name preferences. - Location instructions own same-place identity judgment, separation of nested or uncertain places, and canonical display-name selection. - The shared reconciliation fragment alone owns opaque keys, valid group membership, canonical-member constraints, invention prohibitions, and omission of uncertain groups. Preserve the normalizer order: system, module instructions, cacheable shared reconciliation policy, candidates, cacheable transcript windows. 4. Update module-local prompt preparation tests to assert meaningful relative ordering, input isolation, and cache boundaries. Remove exact message-count assertions whose only purpose was to preserve the former task/instruction split. ### Acceptance criteria - These four prompt directories each contain one module-owned `instructions.md` and no `task.md`. - Scene and normalizer domain policy remains complete but does not repeat universal system, response-schema, or shared reconciliation rules. - Scene chunking still receives the full transcript last; normalizers still receive candidates before transcript windows. - Prompt preparation and existing scene/normalization behavior tests pass. ### Validation ```sh go test ./internal/modules/dnd/chunk/scenes ./internal/modules/dnd/extract/scenedescriptions ./internal/modules/dnd/normalize/npcs ./internal/modules/dnd/normalize/locations git diff --check ``` ## Stage 4: Consolidate NPC, Location, And Item-Event Instructions ### Goal Consolidate three comparatively self-contained extraction prompts and remove their shared or schema-enforced repetition without changing lane semantics. ### Required changes 1. Merge each prompt's `task.md` and `instructions.md` into its existing `instructions.md`, delete `task.md`, and update `prompt.yaml` and the owning manifest for: - NPC extraction; - location extraction; and - item-event extraction. 2. NPC instructions must retain individually identifiable non-PC inclusion, proper-name/stable-title/alias eligibility, all existing exclusion categories, observed display spelling, and the prohibition on invented anonymous labels. Remove generic narrow-range, reference-not-evidence, schema-field, and lore-output restatements already owned elsewhere. 3. Location instructions must retain the current implemented location policy, including the current allowance for a generic label used for a specific place, supported place categories, alias/nesting handling, and domain exclusions. Do **not** implement the future proper-name-only registry policy in this stage. Remove only generic evidence, reference, source-range, and schema-shape repetition. 4. Item-event instructions must retain event eligibility, all five kind definitions, currency treatment, quantity semantics, holder transitions, collective `party` behavior, transfer restrictions, and the distinction between discovery and acquisition. Remove only generic evidence-range, output-envelope, and schema-field restatements. 5. Keep each consolidated extraction instruction as the final ephemeral message. Update focused tests to protect preparation, inputs, output schema, and cache placement without asserting the retired two-message structure. ### Acceptance criteria - The three prompt directories contain no `task.md`. - No domain inclusion, exclusion, event-kind, currency, holder, or location behavior changes. - Generic evidence and response-shape rules have one shared/schema owner. - All three prompts prepare and their extractor tests remain green. ### Validation ```sh go test ./internal/modules/dnd/extract/npcs ./internal/modules/dnd/extract/locations ./internal/modules/dnd/extract/itemevents git diff --check ``` ## Stage 5: Consolidate Spell And Combat-Turn Instructions ### Goal Consolidate the spell and combat-turn prompts while keeping their identity, catalog, grounding, and event semantics in the correct assets. ### Required changes 1. Merge `task.md` and `instructions.md` into `instructions.md`, delete `task.md`, and update `prompt.yaml` and manifests for spells and combat turns. 2. Spell module instructions own: - inclusion of actual casts and unambiguous declared casting attempts; - exclusion of mentions, plans, rules discussion, and unsupported catalog matches; - in-world caster attribution, including player-character and GM-narrated casts; and - the lane-specific requirement that evidence collectively support caster, spell, and casting event. `spell-catalog.md` alone owns the rendered catalog, exact canonical spelling, and the fact that the catalog is recognition context rather than evidence. Shared identity and evidence fragments own their generic rules. 3. Combat-turn instructions own combat-event eligibility and exclusions, chronology, unmatched actors, turn-level evidence grouping, and the `turn_kind` meanings. Remove repeated player/NPC identity grounding, transcript-only evidence, source-range mechanics, and schema-field lists owned by shared assets or the response schema. 4. Keep both consolidated instruction messages final and ephemeral. Preserve the spell catalog and optional NPC grounding as separate variable-context messages after evidence policy and before module instructions. ### Acceptance criteria - Both prompt directories contain no `task.md`. - Spell recognition remains catalog-constrained and caster attribution remains evidence-grounded. - Combat-turn categories, event boundaries, actor policy, and evidence grouping are unchanged. - Neither prompt repeats generic shared identity, evidence, or output-format policy. - Prompt preparation, spell schema/catalog tests, combat tests, and the shared extraction-prefix test pass. ### Validation ```sh go test ./internal/modules/dnd/extract/spells ./internal/modules/dnd/extract/combatturns ./internal/modules/dnd/register git diff --check ``` ## Stage 6: Consolidate Grounded Occurrence And Enemy-Event Instructions ### Goal Finish module prompt consolidation for the three registry- or artifact-grounded event extractors. ### Required changes 1. Merge `task.md` and `instructions.md` into `instructions.md`, delete `task.md`, and update `prompt.yaml` and manifests for: - NPC interactions; - location occurrences; and - enemy events. 2. NPC-interaction instructions own registry membership as an eligibility constraint, occurrence boundaries, all interaction kinds and precedence, combat-alignment splitting, and domain exclusions. The shared NPC fragment owns registry rendering, canonical grounding, and its non-evidence status; shared identity and evidence fragments own their generic rules. 3. Location-occurrence instructions own occurrence eligibility, all occurrence kinds and precedence, handling of speculation, independent overlapping facts, and domain exclusions. `location-registry.md` owns exact ID/name rendering and registry-not-evidence semantics. Remove repeated schema fields, `source_id`, narrow-range, and registry-context language from module prose. 4. Enemy-event instructions own event eligibility, the five event kinds and outcome definitions, one-engagement-per-scene policy, exclusions, and naming of registered or grounded unnamed opponents. `combat-grounding.md` and the shared NPC fragment own rendering and the non-evidence status of auxiliary inputs. The shared evidence fragment owns source-range mechanics. Remove the repeated response-field list and generic evidence statements. 5. Keep each consolidated instruction message final and ephemeral, with all registry and grounding messages before it and after the chunk transcript. ### Acceptance criteria - No D&D prompt directory contains `task.md`. - All occurrence kinds, precedence rules, enemy outcomes, splitting rules, and registry constraints remain intact. - Registry and auxiliary artifacts remain grounding only and never become transcript evidence. - All three prompts prepare, and focused extractor, registry, invariant, and cache-prefix tests pass. ### Validation ```sh go test ./internal/modules/dnd/extract/npcinteractions ./internal/modules/dnd/extract/locationoccurrences ./internal/modules/dnd/extract/enemyevents ./internal/modules/dnd/register git diff --check ``` ## Stage 7: Normalize Private Scene And Spell Schema Identities ### Goal Bring the two outlying private LLM response schemas into the naming convention already used by the other D&D prompt schemas, without touching durable artifact schemas. ### Required changes 1. Normalize the scene private response schema: - rename `assets/dnd/scenes/schemas/dnd_scenes.v1.json` to `dnd_scenes_llm.v1.json`; - change its `$id` from `notarius.dnd.scenes` to `notarius.dnd.scenes.llm`; - change the scene `prompt.yaml` `schema_path` accordingly; and - update `internal/modules/dnd/chunk/scenes/schema.go` to use key `dnd_scenes_llm`, ID `notarius.dnd.scenes.llm`, name `notarius_dnd_scenes_llm_v1`, and the renamed asset path. 2. Normalize the already correctly named spell private response schema: - keep the filename `dnd_spells_llm.v1.json`; - change its `$id` from `notarius.dnd.spells` to `notarius.dnd.spells.llm`; and - update `internal/modules/dnd/extract/spells/schema.go` to use key `dnd_spells_llm`, ID `notarius.dnd.spells.llm`, and name `notarius_dnd_spells_llm_v1`. 3. Keep both versions at `v1`; these are private pre-release response contracts, not a compatibility migration. Do not alter required fields, property types, enum values, `additionalProperties`, or any owning Go response type. 4. Update focused schema-loading, prompt-preparation, registrar, and production composition expectations. Carefully distinguish the private spell response schema from the durable spell artifact schema under `internal/modules/dnd/codec/spells/assets/schemas/`; the durable schema and `docs/integrations/dnd-spell-artifacts.md` must not change. 5. Remove every reference to the retired private scene filename and old private IDs/names/keys. Do not add aliases. ### Acceptance criteria - Scene and spell private schemas use `_llm`/`.llm` consistently in filenames where applicable, registry keys, schema IDs, and response-schema names. - Both schemas still load and validate the same private Go response shapes. - Durable scene chunk-map and spell artifact contracts are unchanged. - Registrar and module prompt preparation tests pass without schema collisions. ### Validation ```sh go test ./internal/modules/dnd/chunk/scenes ./internal/modules/dnd/extract/spells ./internal/modules/dnd/register ./internal/cli git diff --check ``` ## Stage 8: Document Conventions And Perform Final Verification ### Goal Make the implemented conventions discoverable in their canonical documentation, remove stale references, and verify the complete repository. ### Required changes 1. Rewrite the prompt-construction portion of `docs/internal/dnd.md` to describe current implemented behavior: - the canonical `prompt.yaml` and `instructions.md` local names; - module manifests as the owner of selection, order, and fingerprinting; - the `common-dnd-` visual provenance prefix; - the single-owner hierarchy for universal, family, input, module, and schema rules; - the eligibility test for system-prompt content; - the full transcript, chunk transcript, and transcript-window assets and their consumers; - the final extraction, scene-chunking, and entity-normalization message orders and cache controls; - the rule against default prompt repetition and the observational-evidence threshold for reintroducing it; and - the content-only `assets` boundary, with a link to ADR-0011 rather than a duplicate rationale. Remove the current descriptions of separate task and instructions messages and the generic transcript fragment. 2. Do not add an assets-package README or a new ADR. Do not modify ADR-0011. `docs/internal/llm.md` should remain provider-neutral and should not duplicate D&D filenames or ordering. Update it only if an earlier stage changed a provider-neutral PromptKit preparation or cache-control fact; no such change is expected by this plan. 3. Review all changed prompt definitions and manifests as a set. Confirm that: - every prompt has one system message using the shared system asset; - every prompt selects exactly one correct transcript-scope asset; - every extraction prompt retains the stable shared prefix and final ephemeral module instructions; - scene chunking and normalizers retain their intentional distinct orders; - no module-specific prompt repeats a rule already owned by its selected shared assets or response schema; and - the root `assets` Go package remains a single minimal filesystem file with no business logic or internal/PromptKit dependency. 4. Search for stale production references to: - `common-dnd-transcript.md`; - prompt-ID-derived YAML filenames; - D&D `task.md` prompt files; - `catalog.md`, `grounding.md`, and the location-occurrence `locations.md`; - `dnd_scenes.v1.json` and the old scene private schema identity; and - the old spell private schema key, ID, and response-schema name. Exclude historical roadmap text only when the reference intentionally explains a retired name. There should be no stale reference in current code, assets, tests, or implemented documentation. 5. Review tests for policy compliance. Retain behavior-level assertions for preparation, schema compatibility, input isolation, cache placement, and the identical extraction prefix. Remove any leftover assertion whose only value is freezing exact prompt prose, message count, shared-prefix length, or a complete private asset inventory. 6. Run formatting where applicable and the complete offline repository checks. Do not perform live model evaluation. Report that human evaluation with representative transcripts and cost-effective target models remains the next observational step after implementation; do not reintroduce prompt repetition before that evidence exists. ### Acceptance criteria - `docs/internal/dnd.md` accurately describes the implemented prompt layout, ownership, transcript scopes, and cache ordering without duplicating external contracts. - No new ADR or assets README exists, and ADR-0011 remains unchanged. - No stale production references or retired files remain. - All maintained prompts prepare offline, all schemas register, all repository tests and static checks pass, and the CLI builds. - The final diff contains no durable artifact, public module/configuration, or pipeline behavior change. ### Validation ```sh go test ./... go vet ./... go build ./cmd/notarius git diff --check ``` Run `gofmt` on the Go files changed by these stages before the commands above. Inspect the diff and ensure formatting did not rewrite unrelated user changes; never format an entire directory when the worktree contains unrelated edits. ## Open Questions None. The feature roadmap and this plan make the prompt ownership, transcript scope, naming, schema identity, documentation, compatibility, and testing decisions required for implementation.