Implement raw module output contracts
This commit is contained in:
@@ -48,31 +48,30 @@ func TestRunnerProcessesSeriatimInputWithDNDSpellsExtractor(t *testing.T) {
|
||||
t.Fatalf("Run() error = %v, want nil", err)
|
||||
}
|
||||
|
||||
if len(output.Approved) != 2 {
|
||||
t.Fatalf("len(Approved) = %d, want 2", len(output.Approved))
|
||||
if len(output.NormalizeOutputs) != 1 {
|
||||
t.Fatalf("len(NormalizeOutputs) = %d, want 1", len(output.NormalizeOutputs))
|
||||
}
|
||||
var first, second SpellCast
|
||||
if err := json.Unmarshal(output.Approved[0].Payload, &first); err != nil {
|
||||
t.Fatalf("Unmarshal(first payload) error = %v, want nil", err)
|
||||
rawOutput := output.NormalizeOutputs[0]
|
||||
if rawOutput.LaneID != "spells" || rawOutput.Schema.ID != ResponseSchemaID || rawOutput.Schema.Version != SchemaVersion {
|
||||
t.Fatalf("raw output envelope = %#v, want dnd spells schema on spells lane", rawOutput)
|
||||
}
|
||||
if err := json.Unmarshal(output.Approved[1].Payload, &second); err != nil {
|
||||
t.Fatalf("Unmarshal(second payload) error = %v, want nil", err)
|
||||
response := decodeRunnerSpellResponse(t, rawOutput.Payload.Content)
|
||||
if len(response.SpellCasts) != 2 {
|
||||
t.Fatalf("len(spell_casts) = %d, want 2", len(response.SpellCasts))
|
||||
}
|
||||
first, second := response.SpellCasts[0], response.SpellCasts[1]
|
||||
if first.Spell != "Cure Wounds" || second.Spell != "Fire Bolt" {
|
||||
t.Fatalf("approved spell order = %q, %q; want response order", first.Spell, second.Spell)
|
||||
t.Fatalf("spell order = %q, %q; want response order", first.Spell, second.Spell)
|
||||
}
|
||||
if first.Caster != "Aria" || second.Caster != "Borin" {
|
||||
t.Fatalf("approved casters = %q, %q; want spell data", first.Caster, second.Caster)
|
||||
t.Fatalf("casters = %q, %q; want spell data", first.Caster, second.Caster)
|
||||
}
|
||||
for _, artifact := range output.Approved {
|
||||
if artifact.ExtractorKey != Key || artifact.ArtifactType != ArtifactType || artifact.SchemaVersion != SchemaVersion {
|
||||
t.Fatalf("approved artifact envelope = %#v, want dnd spells envelope", artifact)
|
||||
for _, spell := range response.SpellCasts {
|
||||
if len(spell.SourceRefs) != 1 {
|
||||
t.Fatalf("len(SourceRefs) = %d, want 1", len(spell.SourceRefs))
|
||||
}
|
||||
if len(artifact.SourceRefs) != 1 {
|
||||
t.Fatalf("len(SourceRefs) = %d, want 1", len(artifact.SourceRefs))
|
||||
}
|
||||
if err := source.ValidateRef(expectedDoc, artifact.SourceRefs[0]); err != nil {
|
||||
t.Fatalf("ValidateRef() error = %v, want nil", err)
|
||||
if spell.SourceRefs[0].SourceID != expectedDoc.ID {
|
||||
t.Fatalf("SourceID = %q, want fixture document ID", spell.SourceRefs[0].SourceID)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,8 +136,8 @@ func TestRunnerPassesPartyAndGlossaryReferencesToDNDSpellsPrompt(t *testing.T) {
|
||||
t.Fatalf("Run() error = %v, want nil", err)
|
||||
}
|
||||
|
||||
if len(output.Approved) != 1 {
|
||||
t.Fatalf("len(Approved) = %d, want 1", len(output.Approved))
|
||||
if len(output.NormalizeOutputs) != 1 {
|
||||
t.Fatalf("len(NormalizeOutputs) = %d, want 1", len(output.NormalizeOutputs))
|
||||
}
|
||||
if len(output.Manifest.References) != 2 {
|
||||
t.Fatalf("manifest references = %#v, want party and glossary provenance", output.Manifest.References)
|
||||
@@ -178,8 +177,12 @@ func TestRunnerDoesNotExtractSpellMentionedOnlyInPartyReference(t *testing.T) {
|
||||
t.Fatalf("Run() error = %v, want nil", err)
|
||||
}
|
||||
|
||||
if len(output.Approved) != 0 {
|
||||
t.Fatalf("approved artifacts = %#v, want no party-reference-only spell casts", output.Approved)
|
||||
if len(output.NormalizeOutputs) != 1 {
|
||||
t.Fatalf("len(NormalizeOutputs) = %d, want empty spell response output", len(output.NormalizeOutputs))
|
||||
}
|
||||
response := decodeRunnerSpellResponse(t, output.NormalizeOutputs[0].Payload.Content)
|
||||
if len(response.SpellCasts) != 0 {
|
||||
t.Fatalf("spell_casts = %#v, want no party-reference-only spell casts", response.SpellCasts)
|
||||
}
|
||||
if len(llmClient.requests) != 1 {
|
||||
t.Fatalf("LLM calls = %d, want 1", len(llmClient.requests))
|
||||
@@ -196,7 +199,7 @@ func TestRunnerDoesNotExtractSpellMentionedOnlyInPartyReference(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunnerRejectsDNDSpellCastWithInvalidSourceRef(t *testing.T) {
|
||||
func TestRunnerCarriesDNDSpellCastWithInvalidSourceRefAsRawOutput(t *testing.T) {
|
||||
raw := readDNDSpellsFixture(t)
|
||||
resolved := resolveDNDSpellsPipeline(t)
|
||||
llmClient := &fakeSpellsLLMClient{
|
||||
@@ -221,21 +224,21 @@ func TestRunnerRejectsDNDSpellCastWithInvalidSourceRef(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Run() error = %v, want nil", err)
|
||||
}
|
||||
if len(output.Approved) != 0 {
|
||||
t.Fatalf("len(Approved) = %d, want 0", len(output.Approved))
|
||||
if len(output.NormalizeOutputs) != 1 {
|
||||
t.Fatalf("len(NormalizeOutputs) = %d, want 1", len(output.NormalizeOutputs))
|
||||
}
|
||||
if len(output.Rejected) != 1 {
|
||||
t.Fatalf("len(Rejected) = %d, want 1", len(output.Rejected))
|
||||
response := decodeRunnerSpellResponse(t, output.NormalizeOutputs[0].Payload.Content)
|
||||
if len(response.SpellCasts) != 1 {
|
||||
t.Fatalf("len(spell_casts) = %d, want 1", len(response.SpellCasts))
|
||||
}
|
||||
rejected := output.Rejected[0]
|
||||
if rejected.ValidatorName != sourceRefValidatorName {
|
||||
t.Fatalf("ValidatorName = %q, want %q", rejected.ValidatorName, sourceRefValidatorName)
|
||||
if response.SpellCasts[0].SourceRefs[0].SourceID != "spell-session" {
|
||||
t.Fatalf("SourceID = %q, want raw invalid source ref preserved", response.SpellCasts[0].SourceRefs[0].SourceID)
|
||||
}
|
||||
if rejected.ReasonCode != reasonInvalidSourceRef {
|
||||
t.Fatalf("ReasonCode = %q, want %q", rejected.ReasonCode, reasonInvalidSourceRef)
|
||||
if len(output.Rejected) != 0 {
|
||||
t.Fatalf("len(Rejected) = %d, want 0", len(output.Rejected))
|
||||
}
|
||||
if output.Manifest.ValidationStatus != "rejected" {
|
||||
t.Fatalf("ValidationStatus = %q, want rejected", output.Manifest.ValidationStatus)
|
||||
if output.Manifest.ValidationStatus != "approved" {
|
||||
t.Fatalf("ValidationStatus = %q, want approved", output.Manifest.ValidationStatus)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -345,3 +348,13 @@ func parseDNDSpellsFixture(t *testing.T, raw []byte) *source.SourceDocument {
|
||||
}
|
||||
return doc
|
||||
}
|
||||
|
||||
func decodeRunnerSpellResponse(t *testing.T, raw []byte) extractionResponse {
|
||||
t.Helper()
|
||||
|
||||
var response extractionResponse
|
||||
if err := json.Unmarshal(raw, &response); err != nil {
|
||||
t.Fatalf("Unmarshal(raw output) error = %v, want nil", err)
|
||||
}
|
||||
return response
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user