From 39563f3ea03fe93f70b9b5b6308ce42fd578becf Mon Sep 17 00:00:00 2001 From: Eric Rakestraw Date: Wed, 5 Aug 2026 14:59:03 +0000 Subject: [PATCH] Normalize private D&D response schema identities --- assets/dnd/scenes/prompts/prompt.yaml | 2 +- ...nd_scenes.v1.json => dnd_scenes_llm.v1.json} | 2 +- .../dnd/spells/schemas/dnd_spells_llm.v1.json | 2 +- internal/core/artifacts/artifacts_test.go | 4 ++-- internal/framework/llm/schema_registry_test.go | 4 ++-- .../dnd/chunk/scenes/prompt_assets_test.go | 3 +++ internal/modules/dnd/chunk/scenes/schema.go | 8 ++++---- .../modules/dnd/chunk/scenes/schema_test.go | 16 ++++++++-------- internal/modules/dnd/extract/spells/schema.go | 6 +++--- .../modules/dnd/extract/spells/schema_test.go | 17 +++++++++++++---- internal/modules/dnd/register/register_test.go | 2 +- 11 files changed, 39 insertions(+), 27 deletions(-) rename assets/dnd/scenes/schemas/{dnd_scenes.v1.json => dnd_scenes_llm.v1.json} (94%) diff --git a/assets/dnd/scenes/prompts/prompt.yaml b/assets/dnd/scenes/prompts/prompt.yaml index cf6c5c1..2b06d84 100644 --- a/assets/dnd/scenes/prompts/prompt.yaml +++ b/assets/dnd/scenes/prompts/prompt.yaml @@ -30,5 +30,5 @@ messages: output: format: json validation_mode: json_schema - schema_path: dnd_scenes.v1.json + schema_path: dnd_scenes_llm.v1.json repair_attempts: 0 diff --git a/assets/dnd/scenes/schemas/dnd_scenes.v1.json b/assets/dnd/scenes/schemas/dnd_scenes_llm.v1.json similarity index 94% rename from assets/dnd/scenes/schemas/dnd_scenes.v1.json rename to assets/dnd/scenes/schemas/dnd_scenes_llm.v1.json index 3f5713c..7bb4245 100644 --- a/assets/dnd/scenes/schemas/dnd_scenes.v1.json +++ b/assets/dnd/scenes/schemas/dnd_scenes_llm.v1.json @@ -1,6 +1,6 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "notarius.dnd.scenes", + "$id": "notarius.dnd.scenes.llm", "type": "object", "additionalProperties": false, "required": ["scenes"], diff --git a/assets/dnd/spells/schemas/dnd_spells_llm.v1.json b/assets/dnd/spells/schemas/dnd_spells_llm.v1.json index 7dab9ff..71ec207 100644 --- a/assets/dnd/spells/schemas/dnd_spells_llm.v1.json +++ b/assets/dnd/spells/schemas/dnd_spells_llm.v1.json @@ -1,6 +1,6 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "notarius.dnd.spells", + "$id": "notarius.dnd.spells.llm", "type": "object", "additionalProperties": false, "required": ["spell_casts"], diff --git a/internal/core/artifacts/artifacts_test.go b/internal/core/artifacts/artifacts_test.go index c69f79d..ff5d9df 100644 --- a/internal/core/artifacts/artifacts_test.go +++ b/internal/core/artifacts/artifacts_test.go @@ -187,8 +187,8 @@ func TestRunManifestIncludesTopLevelModuleMetadata(t *testing.T) { "prompt_id": "dnd.scenes", "prompt_version": "v1", "prompt_sha256": "sha256:abc123", - "response_schema_key": "dnd_scenes", - "response_schema_name": "dnd_scenes", + "response_schema_key": "dnd_scenes_llm", + "response_schema_name": "notarius_dnd_scenes_llm_v1", }, }, } diff --git a/internal/framework/llm/schema_registry_test.go b/internal/framework/llm/schema_registry_test.go index f647fd4..c713f98 100644 --- a/internal/framework/llm/schema_registry_test.go +++ b/internal/framework/llm/schema_registry_test.go @@ -38,8 +38,8 @@ func TestLookupResponseSchemaUnknownReturnsFalse(t *testing.T) { } } -func TestLookupResponseSchemaDNDSpellsIsNotFrameworkRegistered(t *testing.T) { - if schema, ok := LookupResponseSchema("dnd_spells"); ok { +func TestLookupResponseSchemaDNDSpellsLLMIsNotFrameworkRegistered(t *testing.T) { + if schema, ok := LookupResponseSchema("dnd_spells_llm"); ok { t.Fatalf("expected D&D spells schema lookup to fail in framework registry, got %+v", schema) } } diff --git a/internal/modules/dnd/chunk/scenes/prompt_assets_test.go b/internal/modules/dnd/chunk/scenes/prompt_assets_test.go index 18d6b59..678324c 100644 --- a/internal/modules/dnd/chunk/scenes/prompt_assets_test.go +++ b/internal/modules/dnd/chunk/scenes/prompt_assets_test.go @@ -22,6 +22,9 @@ func TestPromptAssetsPrepareTranscriptWithInstructionOrdering(t *testing.T) { if prepared.PromptID != PromptID { t.Fatalf("prompt id = %q, want %q", prepared.PromptID, PromptID) } + if prepared.OutputContract.SchemaPath != "dnd_scenes_llm.v1.json" { + t.Fatalf("scene output schema path = %q, want private LLM schema", prepared.OutputContract.SchemaPath) + } if len(prepared.Messages) < 4 { t.Fatalf("prepared messages = %#v, want system, references, instructions, and transcript", prepared.Messages) } diff --git a/internal/modules/dnd/chunk/scenes/schema.go b/internal/modules/dnd/chunk/scenes/schema.go index 38e309a..de5f6ef 100644 --- a/internal/modules/dnd/chunk/scenes/schema.go +++ b/internal/modules/dnd/chunk/scenes/schema.go @@ -4,10 +4,10 @@ import "gitea.maximumdirect.net/eric/notarius/internal/framework/llm" const ( PromptID = "dnd.scenes" - ResponseSchemaKey = llm.ResponseSchemaKey("dnd_scenes") - ResponseSchemaID = "notarius.dnd.scenes" + ResponseSchemaKey = llm.ResponseSchemaKey("dnd_scenes_llm") + ResponseSchemaID = "notarius.dnd.scenes.llm" ResponseSchemaVersion = "v1" - ResponseSchemaName = "notarius_dnd_scenes_v1" + ResponseSchemaName = "notarius_dnd_scenes_llm_v1" ) func loadResponseSchema() (llm.ResponseSchema, error) { @@ -20,6 +20,6 @@ func loadResponseSchema() (llm.ResponseSchema, error) { ID: ResponseSchemaID, Version: ResponseSchemaVersion, Name: ResponseSchemaName, - AssetPath: "schemas/dnd_scenes.v1.json", + AssetPath: "schemas/dnd_scenes_llm.v1.json", }) } diff --git a/internal/modules/dnd/chunk/scenes/schema_test.go b/internal/modules/dnd/chunk/scenes/schema_test.go index 4ce2688..8b12b9c 100644 --- a/internal/modules/dnd/chunk/scenes/schema_test.go +++ b/internal/modules/dnd/chunk/scenes/schema_test.go @@ -15,17 +15,17 @@ func TestLoadResponseSchemaForScenes(t *testing.T) { if err != nil { t.Fatalf("loadResponseSchema() error = %v, want nil", err) } - if schema.Key != ResponseSchemaKey { - t.Fatalf("schema.Key = %q, want %q", schema.Key, ResponseSchemaKey) + if got, want := string(schema.Key), "dnd_scenes_llm"; got != want { + t.Fatalf("schema.Key = %q, want %q", got, want) } - if schema.ID != ResponseSchemaID { - t.Fatalf("schema.ID = %q, want %q", schema.ID, ResponseSchemaID) + if got, want := schema.ID, "notarius.dnd.scenes.llm"; got != want { + t.Fatalf("schema.ID = %q, want %q", got, want) } - if schema.Version != ResponseSchemaVersion { - t.Fatalf("schema.Version = %q, want %q", schema.Version, ResponseSchemaVersion) + if got, want := schema.Version, "v1"; got != want { + t.Fatalf("schema.Version = %q, want %q", got, want) } - if schema.Name != ResponseSchemaName { - t.Fatalf("schema.Name = %q, want %q", schema.Name, ResponseSchemaName) + if got, want := schema.Name, "notarius_dnd_scenes_llm_v1"; got != want { + t.Fatalf("schema.Name = %q, want %q", got, want) } if !strings.HasPrefix(schema.SHA256, "sha256:") { t.Fatalf("schema.SHA256 = %q, want sha256 prefix", schema.SHA256) diff --git a/internal/modules/dnd/extract/spells/schema.go b/internal/modules/dnd/extract/spells/schema.go index 40aca30..b073e4a 100644 --- a/internal/modules/dnd/extract/spells/schema.go +++ b/internal/modules/dnd/extract/spells/schema.go @@ -4,9 +4,9 @@ import "gitea.maximumdirect.net/eric/notarius/internal/framework/llm" const ( PromptID = "dnd.spells" - ResponseSchemaKey = llm.ResponseSchemaKey("dnd_spells") - ResponseSchemaID = "notarius.dnd.spells" - ResponseSchemaName = "notarius_dnd_spells_v1" + ResponseSchemaKey = llm.ResponseSchemaKey("dnd_spells_llm") + ResponseSchemaID = "notarius.dnd.spells.llm" + ResponseSchemaName = "notarius_dnd_spells_llm_v1" ) func loadResponseSchema() (llm.ResponseSchema, error) { diff --git a/internal/modules/dnd/extract/spells/schema_test.go b/internal/modules/dnd/extract/spells/schema_test.go index 1f603bb..8c62528 100644 --- a/internal/modules/dnd/extract/spells/schema_test.go +++ b/internal/modules/dnd/extract/spells/schema_test.go @@ -14,8 +14,17 @@ func TestLoadResponseSchemaUsesExtractorOwnedLLMSchema(t *testing.T) { if err != nil { t.Fatalf("loadResponseSchema() error = %v, want nil", err) } - if schema.Key != ResponseSchemaKey || schema.ID != ResponseSchemaID || schema.Version != SchemaVersion || schema.Name != ResponseSchemaName { - t.Fatalf("schema identity = %#v, want maintained response identity", schema) + if got, want := string(schema.Key), "dnd_spells_llm"; got != want { + t.Fatalf("schema key = %q, want %q", got, want) + } + if got, want := schema.ID, "notarius.dnd.spells.llm"; got != want { + t.Fatalf("schema ID = %q, want %q", got, want) + } + if got, want := schema.Version, "v1"; got != want { + t.Fatalf("schema version = %q, want %q", got, want) + } + if got, want := schema.Name, "notarius_dnd_spells_llm_v1"; got != want { + t.Fatalf("schema name = %q, want %q", got, want) } if !strings.HasPrefix(schema.SHA256, "sha256:") || !json.Valid(schema.JSONSchema) { t.Fatalf("schema metadata = %#v, want valid hashed JSON", schema) @@ -24,8 +33,8 @@ func TestLoadResponseSchemaUsesExtractorOwnedLLMSchema(t *testing.T) { if err := json.Unmarshal(schema.JSONSchema, &schemaDocument); err != nil { t.Fatalf("Unmarshal(schema.JSONSchema) error = %v, want nil", err) } - if schemaDocument["$id"] != ResponseSchemaID { - t.Fatalf("schema $id = %#v, want %q", schemaDocument["$id"], ResponseSchemaID) + if schemaDocument["$id"] != "notarius.dnd.spells.llm" { + t.Fatalf("schema $id = %#v, want private LLM schema ID", schemaDocument["$id"]) } valid := validSpellsResponse() diff --git a/internal/modules/dnd/register/register_test.go b/internal/modules/dnd/register/register_test.go index 4d33628..052f674 100644 --- a/internal/modules/dnd/register/register_test.go +++ b/internal/modules/dnd/register/register_test.go @@ -296,7 +296,7 @@ func TestRegisterAddsDNDFamily(t *testing.T) { t.Fatalf("NPC interaction merge validator chain = %#v, want absent", got) } assertAssetNamesContain(t, assets.SchemaFS, []string{ - "dnd_scenes.v1.json", + "dnd_scenes_llm.v1.json", "dnd_spells_llm.v1.json", "dnd_npcs_llm.v1.json", "dnd_combat_turns_llm.v1.json",