package proposal_generation import ( "context" "errors" "testing" "gitea.maximumdirect.net/eric/audita/internal/core/config" "gitea.maximumdirect.net/eric/audita/internal/core/schema" "gitea.maximumdirect.net/eric/audita/internal/framework/contracts" "gitea.maximumdirect.net/eric/audita/internal/framework/proposals" "gitea.maximumdirect.net/eric/audita/internal/prompts" ) func TestExecuteModuleProposalBuildsMessagesFromSectionAndDescription(t *testing.T) { client := &fakeStructuredClient{ responses: []StructuredCorrectionSet{ {Corrections: []StructuredCorrectionProposal{{TargetSegmentID: 1, OriginalText: "teh", CorrectedText: "the", Confidence: 0.9}}}, }, } section := contracts.SectionMetadata{Index: 7} cfg := config.Default() cfg.TranscriptDescription = "Hearing transcript with role titles." transcript := &schema.Transcript{Segments: []schema.Segment{{ID: 1, Speaker: "A", Start: 0, End: 1, Text: "teh"}}} glossary := &schema.Glossary{Entries: []schema.GlossaryEntry{{Name: "X"}}} var gotSectionIndex int var gotDescription string var gotTranscript *schema.Transcript var gotGlossary *schema.Glossary out, err := ExecuteModuleProposal(context.Background(), ModuleProposalRequest{ ProposalRequest: contracts.ProposalRequest{ ExecutionContext: contracts.ExecutionContext{ Config: &cfg, WorkingTranscript: transcript, Glossary: glossary, Section: §ion, }, RunSpec: contracts.ModuleRunSpec{ ModuleKey: "grammar", InstanceName: "grammar", ReplacementPolicy: proposals.ReplacementPolicyRequireUnique, }, LLMClient: client, }, PromptID: prompts.PromptIDModuleGrammarProposal, BuildMessages: func(inTranscript *schema.Transcript, inGlossary *schema.Glossary, sectionIndex int, transcriptDescription string) ([]contracts.LLMMessage, error) { gotSectionIndex = sectionIndex gotDescription = transcriptDescription gotTranscript = inTranscript gotGlossary = inGlossary return []contracts.LLMMessage{{Role: "system", Content: "sys"}, {Role: "user", Content: "usr"}}, nil }, }) if err != nil { t.Fatalf("ExecuteModuleProposal error: %v", err) } if gotSectionIndex != 7 { t.Fatalf("section index: got=%d want=%d", gotSectionIndex, 7) } if gotDescription != cfg.TranscriptDescription { t.Fatalf("transcript description: got=%q want=%q", gotDescription, cfg.TranscriptDescription) } if gotTranscript != transcript { t.Fatalf("expected shared transcript pointer") } if gotGlossary != glossary { t.Fatalf("expected shared glossary pointer") } if len(client.calls) != 1 || client.calls[0].StageName != "grammar:proposal:section-0007" { t.Fatalf("unexpected stage name calls: %+v", client.calls) } if len(out.Proposals) != 1 || out.Proposals[0].CorrectedText != "the" { t.Fatalf("unexpected proposals: %+v", out) } } func TestExecuteModuleProposalValidatesInputs(t *testing.T) { if _, err := ExecuteModuleProposal(context.Background(), ModuleProposalRequest{}); err == nil { t.Fatalf("expected missing message builder error") } _, err := ExecuteModuleProposal(context.Background(), ModuleProposalRequest{ BuildMessages: func(transcript *schema.Transcript, glossary *schema.Glossary, sectionIndex int, transcriptDescription string) ([]contracts.LLMMessage, error) { return nil, nil }, }) if err == nil { t.Fatalf("expected empty prompt ID error") } _, err = ExecuteModuleProposal(context.Background(), ModuleProposalRequest{ PromptID: "missing.prompt.id", BuildMessages: func(transcript *schema.Transcript, glossary *schema.Glossary, sectionIndex int, transcriptDescription string) ([]contracts.LLMMessage, error) { return []contracts.LLMMessage{{Role: "system", Content: "sys"}, {Role: "user", Content: "usr"}}, nil }, }) if err == nil { t.Fatalf("expected unknown prompt ID error") } } func TestExecuteModuleProposalPropagatesBuilderError(t *testing.T) { wantErr := errors.New("builder failed") _, err := ExecuteModuleProposal(context.Background(), ModuleProposalRequest{ PromptID: prompts.PromptIDModuleGlossaryProposal, BuildMessages: func(transcript *schema.Transcript, glossary *schema.Glossary, sectionIndex int, transcriptDescription string) ([]contracts.LLMMessage, error) { return nil, wantErr }, }) if !errors.Is(err, wantErr) { t.Fatalf("expected builder error, got %v", err) } }