package runner import ( "context" "testing" "gitea.maximumdirect.net/eric/audita/v3/internal/core/config" "gitea.maximumdirect.net/eric/audita/v3/internal/core/schema" "gitea.maximumdirect.net/eric/audita/v3/internal/framework/contracts" "gitea.maximumdirect.net/eric/audita/v3/internal/framework/proposals" ) type orderedFactory struct { seen chan contracts.ProposalRequest } func (f orderedFactory) ModuleForSpec(spec contracts.ModuleRunSpec) (contracts.TranscriptModule, error) { return orderedModule{spec: spec, seen: f.seen}, nil } type orderedModule struct { spec contracts.ModuleRunSpec seen chan contracts.ProposalRequest } func (m orderedModule) Key() string { return m.spec.ModuleKey } func (m orderedModule) ReplacementPolicy() proposals.ReplacementPolicy { return proposals.ReplacementPolicyRequireUnique } func (m orderedModule) Validators() []contracts.Validator { return nil } func (m orderedModule) Propose(_ context.Context, req contracts.ProposalRequest) (contracts.ProposalResult, error) { m.seen <- req original, corrected := "party", "Party" if m.spec.Index == 1 { original, corrected = "spell", "Spell" } if m.spec.Index == 2 { original, corrected = "Party Spell", "Party Spell!" } return contracts.ProposalResult{Proposals: []proposals.CorrectionProposal{{TargetSegmentID: 1, OriginalText: original, CorrectedText: corrected, Confidence: 1}}}, nil } func TestOrderedWorkflowUsesIndependentSelectionsAndPriorEdits(t *testing.T) { cfg := &config.Config{GlossaryCollections: map[string]config.GlossaryCollection{ "party": {Entries: []config.GlossaryEntry{{ID: "party", Name: "Party", Category: "person"}}}, "spells": {Entries: []config.GlossaryEntry{{ID: "spell", Name: "Spell", Category: "spell"}}}, }, Pipeline: config.Pipeline{Stages: []config.Stage{ {Module: "glossary", Glossaries: []string{"party"}, ProtectedTerms: []string{"party", "spells"}, Context: config.Context{Description: "party context"}}, {Module: "glossary", Glossaries: []string{"spells"}, ProtectedTerms: []string{"party", "spells"}, Context: config.Context{Description: "spell context"}}, {Module: "grammar", Glossaries: []string{"party", "spells"}, ProtectedTerms: []string{"party", "spells"}}, }}} seen := make(chan contracts.ProposalRequest, 3) output, err := New(orderedFactory{seen: seen}).Run(context.Background(), RunInput{Transcript: &schema.Transcript{Segments: []schema.Segment{{ID: 1, Text: "party spell"}}}, ModuleSpecs: contracts.ResolveModuleRunSpecs(cfg)}) if err != nil { t.Fatal(err) } if got := output.FinalTranscript.Segments[0].Text; got != "Party Spell!" { t.Fatalf("final text = %q", got) } first, second, third := <-seen, <-seen, <-seen if first.Settings.Context.Description != "party context" || second.Settings.Context.Description != "spell context" || len(first.Glossary) != 1 || first.Glossary[0].Name != "Party" || len(second.Glossary) != 1 || second.Glossary[0].Name != "Spell" || len(third.Glossary) != 2 { t.Fatalf("incorrect context: %+v %+v %+v", first, second, third) } if second.WorkingTranscript.Segments[0].Text != "Party spell" || third.WorkingTranscript.Segments[0].Text != "Party Spell" { t.Fatalf("edits not carried forward: %q, %q", second.WorkingTranscript.Segments[0].Text, third.WorkingTranscript.Segments[0].Text) } }