package ucca import "testing" func bindingRes(label, reg, jur string, score float64) LegalSearchResult { return LegalSearchResult{ArticleLabel: label, RegulationShort: reg, SourceClass: "binding_law", AuthorityWeight: 100, Jurisdiction: jur, Score: score} } func guidanceRes(label, reg string, score float64) LegalSearchResult { return LegalSearchResult{ArticleLabel: label, RegulationShort: reg, SourceClass: "supervisory_guidance", AuthorityWeight: 70, Jurisdiction: "EU", Score: score} } func foreignRes(label string, score float64) LegalSearchResult { return LegalSearchResult{ArticleLabel: label, RegulationShort: "RevDSG", SourceClass: "foreign_law", AuthorityWeight: 0, Jurisdiction: "CH", Score: score} } // Acceptance criteria (Phase 1) expressed as ordering tests. func TestRerankByAuthority_Acceptance(t *testing.T) { t.Run("guidance does not overtake semantically competitive binding", func(t *testing.T) { out := rerankByAuthority("Was gilt hier?", []LegalSearchResult{ guidanceRes("ENISA Mapping", "ENISA", 0.72), bindingRes("CRA Anhang I", "CRA", "EU", 0.66), }) if out[0].RegulationShort != "CRA" { t.Fatalf("binding must rank first over competitive guidance, got %q", out[0].RegulationShort) } }) t.Run("foreign law demoted on DE/EU question but kept", func(t *testing.T) { in := []LegalSearchResult{foreignRes("RevDSG Art 1", 0.85), bindingRes("Art. 9 DSGVO", "DSGVO", "EU", 0.62)} out := rerankByAuthority("Welche Daten sind besonders geschuetzt?", in) if out[0].RegulationShort != "DSGVO" { t.Fatalf("binding EU must beat foreign on a DE/EU query, got %q", out[0].RegulationShort) } if len(out) != 2 { t.Fatalf("foreign law must be kept, got len=%d", len(out)) } }) t.Run("off-domain binding demoted but not removed", func(t *testing.T) { in := []LegalSearchResult{ bindingRes("Art. 13 EU MDR", "MDR", "EU", 0.70), bindingRes("Art. 13 CRA", "CRA", "EU", 0.60), } out := rerankByAuthority("Welche Pflichten hat der Hersteller von Produkten mit digitalen Elementen?", in) if out[0].RegulationShort != "CRA" { t.Fatalf("on-domain CRA must beat off-domain MDR, got %q", out[0].RegulationShort) } if len(out) != 2 { t.Fatalf("off-domain MDR must be kept, got len=%d", len(out)) } }) t.Run("same-regime binding wins over guidance", func(t *testing.T) { out := rerankByAuthority("Was gilt hier?", []LegalSearchResult{ bindingRes("Art. 13 CRA", "CRA", "EU", 0.70), guidanceRes("ENISA Mapping", "ENISA", 0.60), }) if out[0].RegulationShort != "CRA" { t.Fatalf("binding must win, got %q", out[0].RegulationShort) } }) t.Run("BDSG Teil 3 demoted below DSGVO on general DP question", func(t *testing.T) { in := []LegalSearchResult{ bindingRes("ยง 48 BDSG", "BDSG", "DE", 0.70), // Teil 3 (law enforcement) bindingRes("Art. 9 DSGVO", "DSGVO", "EU", 0.62), } out := rerankByAuthority("Was sind besondere Kategorien personenbezogener Daten?", in) if out[0].RegulationShort != "DSGVO" { t.Fatalf("DSGVO must beat BDSG Teil 3 on a general DP question, got %q", out[0].RegulationShort) } }) t.Run("nothing is dropped and topic amplifies", func(t *testing.T) { in := []LegalSearchResult{ guidanceRes("ENISA", "ENISA", 0.72), bindingRes("CRA Anhang I", "CRA", "EU", 0.66), foreignRes("RevDSG", 0.5), } out := rerankByAuthority("Anforderungen an Security Updates?", in) if len(out) != len(in) { t.Fatalf("rerank must preserve all results, got %d want %d", len(out), len(in)) } if out[0].ArticleLabel != "CRA Anhang I" { t.Fatalf("topic+authority must lift CRA Anhang I to top, got %q", out[0].ArticleLabel) } }) t.Run("single result returned unchanged", func(t *testing.T) { in := []LegalSearchResult{bindingRes("Art. 1 CRA", "CRA", "EU", 0.5)} if out := rerankByAuthority("x", in); len(out) != 1 { t.Fatalf("len=%d", len(out)) } }) }