433 lines
21 KiB
Markdown
433 lines
21 KiB
Markdown
# D&D Location Tracking Implementation Plan
|
|
|
|
## Objective
|
|
|
|
Complete the target state in [D&D Location Tracking](location.md) by correcting
|
|
the behavioral and maintainability issues found in the post-implementation
|
|
audit. The location registry and occurrence lanes are already implemented and
|
|
production-selectable; the remaining work restores one NPC normalization
|
|
contract, aligns location-occurrence classification with the roadmap, narrows a
|
|
module's declared references, and factors demonstrated registry-resolution
|
|
mechanics into a D&D-shared helper.
|
|
|
|
This is an ordered implementation plan for a `gpt-5.6-terra` coding agent.
|
|
Stages 1 through 14 are complete and must not be reimplemented. Implement one
|
|
new stage per prompt, beginning with Stage 15, and complete each stage's focused
|
|
validation before proceeding.
|
|
|
|
All remaining stages must follow:
|
|
|
|
- [Architecture Policy](../policy/architecture.md);
|
|
- [Testing Policy](../policy/testing.md);
|
|
- [Documentation Policy](../policy/documentation.md);
|
|
- [D&D Module Internals](../internal/dnd.md); and
|
|
- the durable policy decisions in [the feature roadmap](location.md).
|
|
|
|
Use behavior-level tests. Do not add tests that freeze exact prompt wording,
|
|
message counts, source layout, shared-prefix length, or other incidental
|
|
implementation details. Prompts and canonical documentation must agree, but
|
|
that agreement is a review responsibility rather than a reason to add a
|
|
change-detector test.
|
|
|
|
## Completed Work Summary
|
|
|
|
Stages 1 through 14 delivered the following production state:
|
|
|
|
| Completed stage | Result |
|
|
| --- | --- |
|
|
| Stage 1 | Added location and location-occurrence domain types plus evidence-anchored location identity. |
|
|
| Stage 2 | Added strict `v1` durable codecs and JSON Schemas for both artifact kinds. |
|
|
| Stage 3 | Added shared, opaque-key D&D entity-reconciliation context and proposal safety infrastructure. |
|
|
| Stage 4 | Migrated NPC normalization to the shared reconciliation machinery. |
|
|
| Stage 5 | Added evidence-grounded `dnd/locations` extraction. |
|
|
| Stage 6 | Added conservative LLM-assisted location normalization. |
|
|
| Stage 7 | Added immutable location-registry resolution and source-free `{id, name}` projection. |
|
|
| Stage 8 | Added registry-grounded `dnd/location-occurrences` extraction. |
|
|
| Stage 9 | Added deterministic location-occurrence normalization. |
|
|
| Stage 10 | Added location shape, identity, evidence, and advisory validators. |
|
|
| Stage 11 | Added location-occurrence shape, registry, invariant, evidence, and advisory validators. |
|
|
| Stage 12 | Registered both lanes, their assets, evidence projectors, default profiles, and validator chains. |
|
|
| Stage 13 | Added the ordered generated-reference handoff to the complete D&D example and integration coverage. |
|
|
| Stage 14 | Published the current integration, configuration, internal, output, and top-level documentation and ran final verification. |
|
|
|
|
The post-implementation audit confirmed that the feature's durable types,
|
|
identity derivation, codecs, registration, validators, generated handoff,
|
|
evidence publication, maintained example, and integration coverage are in
|
|
place. At the audit baseline, `go test ./...`, focused race tests, `go vet
|
|
./...`, `go build ./cmd/notarius`, and `git diff --check` all passed.
|
|
|
|
## Stage 15: Restore NPC Canonical-Name Selection Semantics
|
|
|
|
### Goal
|
|
|
|
Restore the NPC-specific canonical display-name policy that was weakened during
|
|
the shared reconciliation migration, without changing the shared proposal
|
|
contract or any durable artifact shape.
|
|
|
|
### Work
|
|
|
|
- Update the NPC normalization task asset under
|
|
`internal/modules/dnd/normalize/npcs/assets/prompts/` so canonical selection
|
|
again applies all of these rules:
|
|
- choose only a supplied candidate from an evidence-supported duplicate
|
|
group;
|
|
- prefer a complete, stable proper name over an abbreviation; and
|
|
- prefer an unadorned proper name over that name plus a contextual class,
|
|
role, title, or relationship descriptor unless the transcript establishes
|
|
the descriptor as part of the person's name.
|
|
- Preserve the opaque-key shared reconciliation instructions, prompt-message
|
|
ordering, response schema, retry/fallback behavior, and deterministic group
|
|
application. Do not move NPC-specific naming policy into
|
|
`shared/entityreconcile`.
|
|
- Update the canonical NPC artifact contract in
|
|
`docs/integrations/dnd-npc-artifacts.md` with the observable canonical-name
|
|
selection rule. Keep `docs/internal/dnd.md` focused on normalization
|
|
mechanics and link to the integration contract rather than maintaining a
|
|
competing definition; add or adjust a link only if needed for clarity.
|
|
- Allow the prompt fingerprint and any derived manifest/checkpoint metadata to
|
|
change through the existing asset-fingerprint mechanism. Do not manually
|
|
pin a digest.
|
|
- Retain existing behavior tests for opaque candidate selection, evidence
|
|
union, ID derivation, retry/fallback, and non-mutation. Add a test only if it
|
|
exercises deterministic code behavior; do not assert prompt prose.
|
|
|
|
### Acceptance Criteria
|
|
|
|
- The rendered NPC normalization prompt contains one unambiguous NPC-owned
|
|
policy that distinguishes proper names from contextual descriptors.
|
|
- `Captain Aria` is not preferred over `Aria` solely because it is longer when
|
|
`Captain` is only a contextual title, while an established full name may
|
|
still outrank an abbreviation.
|
|
- No module key, schema, identity policy, response schema, validator chain, or
|
|
shared reconciliation asset changes.
|
|
- Canonical current documentation, rather than this implementation plan, owns
|
|
the restored externally observable rule.
|
|
- `go test ./internal/modules/dnd/normalize/npcs/... ./internal/modules/dnd/shared/entityreconcile/... ./internal/modules/dnd/register/...`
|
|
passes offline.
|
|
- `git diff --check` reports no errors.
|
|
|
|
### Prompt Size
|
|
|
|
Small and suitable for one implementation prompt.
|
|
|
|
## Stage 16: Correct Hypothetical Location-Occurrence Classification
|
|
|
|
### Goal
|
|
|
|
Make the location-occurrence prompt and durable documentation implement the
|
|
roadmap's distinction between an explicit speculative mention and an inferred
|
|
or unsupported occurrence.
|
|
|
|
### Work
|
|
|
|
- Update the location-occurrence task asset under
|
|
`internal/modules/dnd/extract/locationoccurrences/assets/prompts/` to encode
|
|
these exact semantic outcomes:
|
|
- explicit non-actionable speculation or a mere hypothetical reference to a
|
|
registry location is `mentioned`;
|
|
- an explicit proposal, intention, or agreement to travel is `planned`;
|
|
- a mere hypothetical or speculation is not `planned`; and
|
|
- an inferred, unstated, uncertain, or unsupported place or occurrence is
|
|
omitted.
|
|
- Preserve the documented precedence `visited`, `planned`, `recalled`, then
|
|
`mentioned`, including the ability to return multiple independently
|
|
evidenced facts from one passage.
|
|
- Update the `mentioned` definition in
|
|
`docs/integrations/dnd-location-occurrence-artifacts.md` to explicitly include
|
|
non-actionable speculation. Keep durable category semantics in that
|
|
integration contract and link from internal documentation rather than
|
|
duplicating the taxonomy elsewhere.
|
|
- Do not change the occurrence enum, durable schema, normalizer, validators, or
|
|
generated-reference contract.
|
|
- Allow existing prompt fingerprinting to record the asset change. Do not add
|
|
an exact-text or exact-digest test.
|
|
|
|
### Acceptance Criteria
|
|
|
|
- The prompt no longer instructs the model to omit every hypothetical
|
|
reference.
|
|
- An explicit statement such as “What if we went to Moon Gate?” is eligible as
|
|
`mentioned` when it is supported by a narrow transcript range, but is not a
|
|
`planned` occurrence without an actual proposal or intention.
|
|
- An unstated location inferred only from surrounding events remains omitted.
|
|
- The feature roadmap, prompt, and canonical integration contract agree on all
|
|
four categories and their precedence.
|
|
- `go test ./internal/modules/dnd/extract/locationoccurrences/... ./internal/modules/dnd/register/...`
|
|
passes offline.
|
|
- `git diff --check` reports no errors.
|
|
|
|
### Prompt Size
|
|
|
|
Small and suitable for one implementation prompt.
|
|
|
|
## Stage 17: Narrow Location-Occurrence Normalizer References
|
|
|
|
### Goal
|
|
|
|
Make the deterministic normalizer advertise exactly the reference material it
|
|
uses.
|
|
|
|
### Work
|
|
|
|
- Change `internal/modules/dnd/normalize/locationoccurrences` so its
|
|
`ReferenceSlots` and `ModuleSpec` expose only the required `locations` slot.
|
|
- Keep that slot's existing contract unchanged: exactly one
|
|
`dnd/location-list` artifact, `application/json`, at most 1,048,576 bytes,
|
|
required at extraction and normalization.
|
|
- Remove the normalizer's unused `party`, `roster`, `players`, and `glossary`
|
|
declarations and any imports or description tables made dead by that change.
|
|
Do not remove those optional slots from the LLM-backed occurrence extractor,
|
|
which actually presents campaign material to the model.
|
|
- Add or revise focused module-contract tests to compare the normalizer's
|
|
complete declared slot set, including requiredness, media type, artifact kind,
|
|
and size. This is a stable module contract test, not a source-layout test.
|
|
- Verify that pipeline-level campaign reference defaults continue to bind only
|
|
to eligible targets and that the complete example still resolves. Current
|
|
configuration documentation already states that `locations` is required by
|
|
both occurrence stages; update it only if repository inspection finds a claim
|
|
that optional campaign references are consumed by the normalizer.
|
|
- Do not change normalization output, registry fingerprints, warnings, or
|
|
checkpoint handling for the required generated registry.
|
|
|
|
### Acceptance Criteria
|
|
|
|
- Catalog and `ModuleSpec` inspection report exactly one normalizer reference
|
|
slot: required `locations`.
|
|
- The extractor continues to accept its existing optional campaign context and
|
|
required location registry.
|
|
- Binding optional campaign references no longer implies that deterministic
|
|
occurrence normalization consumes them.
|
|
- The complete configuration and generated location handoff still resolve and
|
|
run through existing tests.
|
|
- `go test ./internal/modules/dnd/normalize/locationoccurrences/... ./internal/modules/dnd/register/... ./internal/modules/integration/... ./internal/cli/...`
|
|
passes offline.
|
|
- `git diff --check` reports no errors.
|
|
|
|
### Prompt Size
|
|
|
|
Small and suitable for one implementation prompt.
|
|
|
|
## Stage 18: Add Shared Registry-Resolution Infrastructure
|
|
|
|
### Goal
|
|
|
|
Introduce a focused D&D-shared primitive for the demonstrated immutable
|
|
registry-resolution mechanics, without changing any production consumer in the
|
|
same prompt.
|
|
|
|
### Work
|
|
|
|
- Add `internal/modules/dnd/shared/registryresolver` as a domain-shared package;
|
|
do not put this helper in the generic framework.
|
|
- Provide an idiomatic generic resolver driven by callbacks or a small adapter
|
|
so it can operate on immutable domain registry views without importing NPC,
|
|
location, scene-description, or codec packages.
|
|
- The resolver core must own the behavior currently duplicated by the NPC and
|
|
location resolvers:
|
|
- validate and retain one construction-time seeded view;
|
|
- treat a declared generated-reference placeholder with zero construction-
|
|
time items as absent only during construction;
|
|
- use the seeded view when an operation does not supply the target slot;
|
|
- resolve an operation-time override when the target slot is present;
|
|
- memoize valid immutable views by a raw key and by semantic identity;
|
|
- reuse the seeded view when bound state and semantic identity match;
|
|
- synchronize concurrent resolution; and
|
|
- never retain caller-owned reference maps, item content, or mutable values.
|
|
- Raw cache identity must normalize the media-type spelling and hash the actual
|
|
item content. Do not trust a caller-supplied digest as proof that different
|
|
bytes are equal.
|
|
- Provide a narrow helper for resolving an optional single reference item that
|
|
validates the configured slot name, exact item count when bound, parsed media
|
|
type, and maximum size. Return owned bytes or require immediate decode so the
|
|
helper cannot retain caller-owned content.
|
|
- Keep artifact decoding, semantic identity validation, canonical encoding,
|
|
prompt projection, lookup indexes, clone policy, and domain-specific error
|
|
context in the owning registry packages.
|
|
- Keep errors bounded and content-free. Do not include raw reference bytes,
|
|
origin paths, or campaign data in diagnostics.
|
|
- Add focused tests for absent construction state, zero-item generated
|
|
placeholders, seeded fallback, operation overrides, malformed cardinality,
|
|
media types, size limits, raw reuse, semantic reuse, caller-supplied digest
|
|
mismatch, concurrent access, loader failure, and non-retention/non-mutation.
|
|
|
|
### Acceptance Criteria
|
|
|
|
- The shared package depends only on generic source/framework contracts and Go
|
|
standard-library packages, not concrete D&D artifact or codec packages.
|
|
- The helper owns only demonstrated resolution, validation, caching, and
|
|
ownership mechanics; it does not become a universal artifact registry.
|
|
- Invalid values and loader errors are never cached.
|
|
- Concurrent callers resolving identical bytes receive the same prepared
|
|
immutable view without races.
|
|
- Existing production registry packages remain unchanged in this stage.
|
|
- `go test -race ./internal/modules/dnd/shared/registryresolver/...` passes
|
|
offline.
|
|
- `git diff --check` reports no errors.
|
|
|
|
### Prompt Size
|
|
|
|
Medium and suitable for one implementation prompt. Keep production migrations
|
|
out of this stage so the generic ownership and concurrency contract can be
|
|
reviewed independently.
|
|
|
|
## Stage 19: Migrate The NPC Registry To The Shared Resolver
|
|
|
|
### Goal
|
|
|
|
Make the established NPC registry the first production consumer of the shared
|
|
resolver while preserving all public and operational behavior.
|
|
|
|
### Work
|
|
|
|
- Refactor `internal/modules/dnd/npcs/registry` to compose the Stage 18 helper
|
|
for construction/operation selection, single-item validation, raw caching,
|
|
semantic caching, and synchronization.
|
|
- Preserve the existing package API used by extractors, normalizers,
|
|
validators, manifests, and tests, including `NewResolver`, `Resolve`,
|
|
`Seeded`, `Bound`, `NPCs`, `List`, `CanonicalBytes`, `Digest`,
|
|
`ProjectionDigest`, `Count`, `PromptInput`, `CanonicalName`, and `Matches`.
|
|
- Keep NPC-owned behavior in the NPC package:
|
|
- strict approved NPC codec use;
|
|
- NPC identity validation;
|
|
- canonical durable JSON and names-only prompt projection;
|
|
- comparison-key lookup;
|
|
- defensive NPC/source-reference cloning; and
|
|
- NPC-specific redacted error context.
|
|
- Preserve the exact empty projection, semantic and projection digest behavior,
|
|
seeded/generated resolution semantics, manifest metadata, checkpoint
|
|
fingerprints, and source-free prompt input.
|
|
- Remove superseded NPC-private resolver/cache/media/digest code only after the
|
|
shared helper supplies the same behavior. Do not migrate locations or scene
|
|
descriptions in this stage.
|
|
- Update focused tests as needed to verify behavior through the NPC package,
|
|
including malformed static and operation-time references, raw/semantic cache
|
|
reuse, concurrent resolution, defensive copies, prompt projection, and
|
|
downstream grounding.
|
|
|
|
### Acceptance Criteria
|
|
|
|
- Existing NPC consumers compile without API changes.
|
|
- NPC registry output bytes, prompt projection, lookup behavior, digests,
|
|
reference limits, errors, manifests, and checkpoints retain their established
|
|
semantics.
|
|
- The NPC package no longer contains a second implementation of resolver
|
|
selection, caching, or synchronization.
|
|
- `go test -race ./internal/modules/dnd/npcs/registry/... ./internal/modules/dnd/extract/npcinteractions/... ./internal/modules/dnd/normalize/npcinteractions/... ./internal/modules/dnd/validate/npcinteractions/...`
|
|
passes offline.
|
|
- `go test ./internal/modules/dnd/register/...` passes offline.
|
|
- `git diff --check` reports no errors.
|
|
|
|
### Prompt Size
|
|
|
|
Medium and suitable for one implementation prompt.
|
|
|
|
## Stage 20: Migrate The Location Registry To The Shared Resolver
|
|
|
|
### Goal
|
|
|
|
Remove the newly introduced NPC/location resolver duplication while preserving
|
|
the location identity and generated-handoff contracts.
|
|
|
|
### Work
|
|
|
|
- Refactor `internal/modules/dnd/locations/registry` to compose the Stage 18
|
|
helper for the same resolver, reference-item validation, cache, and
|
|
synchronization responsibilities migrated in Stage 19.
|
|
- Preserve the existing package API, including `NewResolver`, `Resolve`,
|
|
`Seeded`, `Bound`, `Locations`, `List`, `CanonicalBytes`, `Digest`,
|
|
`ProjectionDigest`, `Count`, `PromptInput`, `Lookup`, and `Matches`.
|
|
- Keep location-owned behavior in the location package:
|
|
- strict approved location codec use;
|
|
- evidence-anchored identity validation;
|
|
- canonical durable JSON and ordered source-free `{id, name}` projection;
|
|
- exact ID lookup and exact ID/name matching;
|
|
- defensive location/source-reference cloning; and
|
|
- location-specific redacted error context.
|
|
- Preserve absent/empty/bound distinctions, same-name locations with distinct
|
|
IDs, seeded/generated resolution, semantic and projection digests, manifest
|
|
metadata, checkpoint fingerprints, and the 1 MiB limit.
|
|
- Remove superseded location-private resolver/cache/media/digest code only
|
|
after parity is established.
|
|
- Do not migrate the scene-description eligibility registry in this stage. It
|
|
has a different projection and matching contract; including it is not needed
|
|
to eliminate the exact NPC/location duplication identified by the audit.
|
|
- Update focused and integration tests as needed for static and generated
|
|
references, malformed inputs, raw/semantic reuse, concurrency, defensive
|
|
copies, source-free projections, same-name ID lookup, normalizer grounding,
|
|
validator grounding, and handoff checkpoint invalidation.
|
|
|
|
### Acceptance Criteria
|
|
|
|
- Existing location consumers compile without API changes.
|
|
- Location registry output bytes, projection, identity validation, lookup,
|
|
digests, reference errors, manifests, and checkpoints retain their
|
|
established semantics.
|
|
- NPC and location registries share one implementation of construction/
|
|
operation resolution, raw and semantic caching, and synchronization.
|
|
- No registry evidence or provenance appears in the occurrence prompt
|
|
projection.
|
|
- `go test -race ./internal/modules/dnd/locations/registry/... ./internal/modules/dnd/extract/locationoccurrences/... ./internal/modules/dnd/normalize/locationoccurrences/... ./internal/modules/dnd/validate/locationoccurrences/... ./internal/modules/integration/...`
|
|
passes offline.
|
|
- `git diff --check` reports no errors.
|
|
|
|
### Prompt Size
|
|
|
|
Medium and suitable for one implementation prompt.
|
|
|
|
## Stage 21: Final Regression And Documentation Verification
|
|
|
|
### Goal
|
|
|
|
Verify the remediations as one coherent production state without expanding the
|
|
feature or prematurely retiring its roadmap documents.
|
|
|
|
### Work
|
|
|
|
- Run `gofmt` on all changed Go files and inspect the final diff for unrelated
|
|
changes, stale private resolver implementations, unused imports, and
|
|
accidental artifact-contract changes.
|
|
- Re-read the affected prompt assets and canonical integration documents to
|
|
verify that:
|
|
- NPC canonical-name selection retains the proper-name/title distinction;
|
|
- explicit non-actionable speculation maps to `mentioned`;
|
|
- inferred, uncertain, and unsupported occurrences remain omitted; and
|
|
- prompt changes did not reorder or duplicate shared cacheable prompt assets.
|
|
- Inspect module catalog output or registration tests to confirm the
|
|
location-occurrence normalizer declares only `locations`, while its extractor
|
|
retains the intended optional campaign slots.
|
|
- Confirm the shared resolver has exactly the NPC and location consumers
|
|
planned here and that domain-specific codecs, identity, projections, lookups,
|
|
and error context remain in their owning packages.
|
|
- Run the maintained complete example/configuration loading path and all
|
|
repository-wide validation.
|
|
- Leave `docs/roadmap/location.md` and this implementation plan in place for the
|
|
user's separate roadmap-retirement step. Do not delete them in this stage.
|
|
|
|
### Acceptance Criteria
|
|
|
|
- `go test ./internal/modules/dnd/...` passes.
|
|
- `go test ./internal/modules/integration/... ./internal/cli/...` passes.
|
|
- `go test -race ./internal/modules/dnd/shared/registryresolver/... ./internal/modules/dnd/npcs/registry/... ./internal/modules/dnd/locations/registry/...` passes.
|
|
- `go test ./...` passes.
|
|
- `go vet ./...` passes.
|
|
- `go build ./cmd/notarius` passes.
|
|
- Maintained configuration/example validation passes through its repository
|
|
test target.
|
|
- `git diff --check` reports no errors.
|
|
- Current documentation contains no stale contradiction about hypothetical
|
|
location mentions or NPC canonical-name selection.
|
|
- The worktree contains only the intended remediation changes and the roadmap
|
|
documents remain available for later retirement.
|
|
|
|
### Prompt Size
|
|
|
|
Small-to-medium and suitable for one implementation prompt.
|
|
|
|
## Open Questions
|
|
|
|
None. The feature roadmap and audit findings determine the required behavioral
|
|
semantics, module reference contract, abstraction boundary, migration order,
|
|
and validation expectations. The scene-description eligibility registry is
|
|
explicitly outside this remediation because its projection and matching
|
|
semantics differ from the duplicated NPC/location grounding registries.
|