Files
notarius/docs/roadmap/implementation.md

619 lines
27 KiB
Markdown

# 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.