From 87385b7e141d35cd8e102b090b8c8fa6b95ae925 Mon Sep 17 00:00:00 2001 From: Eric Rakestraw Date: Fri, 28 Aug 2026 00:20:59 +0000 Subject: [PATCH] Register optional combat semantics validator --- docs/roadmap/implementation.md | 2 ++ internal/modules/dnd/register/modules.go | 2 ++ internal/modules/dnd/register/register_test.go | 6 ++++++ internal/modules/dnd/register/validators.go | 2 ++ 4 files changed, 12 insertions(+) diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md index 6d0f6f36..452001f1 100644 --- a/docs/roadmap/implementation.md +++ b/docs/roadmap/implementation.md @@ -253,6 +253,8 @@ This stage is small enough for one implementation prompt. ## Stage 4: Register And Resolve The Optional Validator +✅ Complete + ### Goal Expose the module through production D&D composition and prove explicit diff --git a/internal/modules/dnd/register/modules.go b/internal/modules/dnd/register/modules.go index fdf14505..02c8e8a2 100644 --- a/internal/modules/dnd/register/modules.go +++ b/internal/modules/dnd/register/modules.go @@ -35,6 +35,7 @@ import ( npcnormalize "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/normalize/npcregistry" scenedescriptionnormalize "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/normalize/scenedescriptions" spellnormalize "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/normalize/spells" + combatsemantics "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/scenedescriptions/combat_semantics" "gitea.maximumdirect.net/eric/notarius/internal/modules/generic/merge/appendorder" "gitea.maximumdirect.net/eric/notarius/internal/modules/generic/normalize/noop" ) @@ -157,6 +158,7 @@ func registerPromptAssets(assets *llm.AssetRegistry) error { {name: "item registry normalization prompt assets", register: func() error { return itemregistrynormalize.RegisterPromptAssets(assets) }}, {name: "npc occurrences prompt assets", register: func() error { return occurrenceextract.RegisterPromptAssets(assets) }}, {name: "scene descriptions prompt assets", register: func() error { return scenedescriptionextract.RegisterPromptAssets(assets) }}, + {name: "scene combat-semantics validator prompt assets", register: func() error { return combatsemantics.RegisterPromptAssets(assets) }}, {name: "location registry prompt assets", register: func() error { return locationextract.RegisterPromptAssets(assets) }}, {name: "location normalization prompt assets", register: func() error { return locationnormalize.RegisterPromptAssets(assets) }}, {name: "location occurrences prompt assets", register: func() error { return locationoccurrenceextract.RegisterPromptAssets(assets) }}, diff --git a/internal/modules/dnd/register/register_test.go b/internal/modules/dnd/register/register_test.go index 90212e9b..26b989f4 100644 --- a/internal/modules/dnd/register/register_test.go +++ b/internal/modules/dnd/register/register_test.go @@ -31,6 +31,7 @@ import ( npcnormalize "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/normalize/npcregistry" scenedescriptionnormalize "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/normalize/scenedescriptions" spellnormalize "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/normalize/spells" + combatsemantics "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/scenedescriptions/combat_semantics" ) func TestRegisterAddsDNDFamily(t *testing.T) { @@ -57,6 +58,7 @@ func TestRegisterAddsDNDFamily(t *testing.T) { "dnd.item_registry.normalize/prompt.yaml", "dnd.npc_occurrences/prompt.yaml", "dnd.scene_descriptions/prompt.yaml", + "dnd.scene_descriptions.validate_combat/prompt.yaml", "dnd.npc_registry.normalize/prompt.yaml", "dnd.location_registry/prompt.yaml", "dnd.location_registry.normalize/prompt.yaml", @@ -124,10 +126,14 @@ func TestRegisterAddsDNDFamily(t *testing.T) { "extract/dnd/scene-descriptions/shape", "extract/dnd/scene-descriptions/source_refs", "extract/dnd/scene-descriptions/source_relatedness", + combatsemantics.Key, "normalize/dnd/scene-descriptions/invariants", "generic/always_accept", "generic/always_reject", }) + if spec, ok := registries.Validators.Spec(combatsemantics.Key); !ok || spec.Key != combatsemantics.Key || spec.ExecutionClass != contracts.ExecutionClassLLMBacked { + t.Fatalf("combat semantics validator spec = %#v, present=%t; want registered LLM-backed scene validator", spec, ok) + } locationExtractChain := []pipeline.ModuleBinding{pipeline.Binding("generic/valid_json"), pipeline.Binding("extract/dnd/location-registry/shape"), pipeline.Binding("extract/dnd/location-registry/source_refs"), pipeline.Binding("generic/valid_json_schema"), pipeline.Binding("extract/dnd/location-registry/source_relatedness")} locationNormalizeChain := []pipeline.ModuleBinding{pipeline.Binding("generic/valid_json"), pipeline.Binding("extract/dnd/location-registry/shape"), pipeline.Binding("normalize/dnd/location-registry/identity"), pipeline.Binding("extract/dnd/location-registry/source_refs"), pipeline.Binding("generic/valid_json_schema"), pipeline.Binding("extract/dnd/location-registry/source_relatedness")} occurrenceExtractChain := []pipeline.ModuleBinding{pipeline.Binding("generic/valid_json"), pipeline.Binding("extract/dnd/location-occurrences/shape"), pipeline.Binding("extract/dnd/location-occurrences/registry"), pipeline.Binding("extract/dnd/location-occurrences/source_refs"), pipeline.Binding("generic/valid_json_schema"), pipeline.Binding("extract/dnd/location-occurrences/source_relatedness")} diff --git a/internal/modules/dnd/register/validators.go b/internal/modules/dnd/register/validators.go index 5a9d0b34..fd3eec52 100644 --- a/internal/modules/dnd/register/validators.go +++ b/internal/modules/dnd/register/validators.go @@ -39,6 +39,7 @@ import ( npcshape "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/npcregistry/shape" npcsourcerefs "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/npcregistry/source_refs" npcrelatedness "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/npcregistry/source_relatedness" + combatsemantics "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/scenedescriptions/combat_semantics" sceneinvariants "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/scenedescriptions/invariants" sceneshape "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/scenedescriptions/shape" scenerefs "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/scenedescriptions/source_refs" @@ -87,6 +88,7 @@ func registerValidators(registries pipeline.Registries) error { {name: "scene description shape validator", register: func() error { return sceneshape.Register(registries.Validators) }}, {name: "scene description source references validator", register: func() error { return scenerefs.Register(registries.Validators) }}, {name: "scene description source relatedness validator", register: func() error { return scenerelatedness.Register(registries.Validators) }}, + {name: "scene description combat semantics validator", register: func() error { return combatsemantics.Register(registries.Validators) }}, {name: "scene description normalized invariants validator", register: func() error { return sceneinvariants.Register(registries.Validators) }}, {name: "location shape validator", register: func() error { return locationshape.Register(registries.Validators) }}, {name: "location identity validator", register: func() error { return locationidentity.Register(registries.Validators) }},