From c060ac222a0bcc16dd42bf00f094c12c3affffa6 Mon Sep 17 00:00:00 2001 From: Benjamin Admin Date: Fri, 15 May 2026 09:45:08 +0200 Subject: [PATCH] fix(iace): prioritize zone-specific matches in greedy assignment Sort matches by specificity first (zone overlap), then by score. Prevents generic matches from consuming specific Engine patterns that should match more specific GT entries. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../internal/iace/benchmark_matcher.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) 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