diff --git a/ai-compliance-sdk/internal/iace/benchmark_matcher.go b/ai-compliance-sdk/internal/iace/benchmark_matcher.go index 4c042a5e..54ad39a0 100644 --- a/ai-compliance-sdk/internal/iace/benchmark_matcher.go +++ b/ai-compliance-sdk/internal/iace/benchmark_matcher.go @@ -111,8 +111,17 @@ func CompareBenchmark(gt *GroundTruth, hazards []Hazard, mitigations []Mitigatio } } - // Greedy best-first 1:1 assignment - sort.Slice(pairs, func(a, b int) bool { return pairs[a].score > pairs[b].score }) + // Greedy assignment: sort by score, but prioritize high-specificity matches + // (matches where both category AND zone overlap) over generic ones + sort.Slice(pairs, func(a, b int) bool { + // First: prioritize matches with zone overlap (more specific) + aHasZone := pairs[a].reason != "" && (strings.Contains(pairs[a].reason, "Zone") || strings.Contains(pairs[a].reason, "Keywords+Zone")) + bHasZone := pairs[b].reason != "" && (strings.Contains(pairs[b].reason, "Zone") || strings.Contains(pairs[b].reason, "Keywords+Zone")) + if aHasZone != bHasZone { + return aHasZone + } + return pairs[a].score > pairs[b].score + }) usedGT := make(map[int]bool) usedEng := make(map[int]bool) var matched []HazardMatchPair