From 69240faf24245f52cc31492c77691730146a4666 Mon Sep 17 00:00:00 2001 From: Benjamin Admin Date: Fri, 15 May 2026 14:45:37 +0200 Subject: [PATCH] fix(iace): accumulate SuggestedMeasureIDs across dedup'd patterns When multiple patterns match the same category+zone, the first creates the hazard and later patterns add their SuggestedMeasureIDs to the existing hazard. This ensures KSS-specific measures (M420) reach the hazard even if a generic pattern created it first. seenCatZone changed from map[string]bool to map[string]uuid.UUID to track which hazard ID was created for each dedupKey. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../api/handlers/iace_handler_init.go | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/ai-compliance-sdk/internal/api/handlers/iace_handler_init.go b/ai-compliance-sdk/internal/api/handlers/iace_handler_init.go index 4543932a..7d8f4175 100644 --- a/ai-compliance-sdk/internal/api/handlers/iace_handler_init.go +++ b/ai-compliance-sdk/internal/api/handlers/iace_handler_init.go @@ -160,32 +160,35 @@ func (h *IACEHandler) InitializeProject(c *gin.Context) { } created := 0 - seenCatZone := make(map[string]bool) + seenCatZone := make(map[string]uuid.UUID) // dedupKey → hazardID catCount := make(map[string]int) for _, mp := range matchOutput.MatchedPatterns { - // Narrative relevance filter: skip patterns whose zone/scenario - // mentions machine-specific terms that don't appear in our components + // Narrative relevance filter if !isPatternRelevant(mp, narrativeText, compNames) { continue } for _, cat := range mp.HazardCats { - // Per-category cap: limit hazards per category based on relevance maxForCat := categoryHazardCap(cat, len(comps)) if catCount[cat] >= maxForCat { continue } - // Dedup by category + normalized zone zoneKey := normalizeZoneKey(mp.ZoneDE) if zoneKey == "" { zoneKey = mp.PatternID } dedupKey := cat + ":" + zoneKey - if seenCatZone[dedupKey] { + + // If this dedupKey already exists but current pattern has + // SuggestedMeasureIDs, add them to the existing hazard + if existingHzID, exists := seenCatZone[dedupKey]; exists { + if len(mp.SuggestedMeasureIDs) > 0 { + existing := hazardPatternMeasures[existingHzID] + hazardPatternMeasures[existingHzID] = append(existing, mp.SuggestedMeasureIDs...) + } continue } - seenCatZone[dedupKey] = true name := mp.PatternName if name == "" { @@ -226,8 +229,8 @@ func (h *IACEHandler) InitializeProject(c *gin.Context) { if cerr == nil { created++ catCount[cat]++ + seenCatZone[dedupKey] = hz.ID hazardIDsByCategory[cat] = append(hazardIDsByCategory[cat], hz.ID) - // Remember this pattern's suggested measures for this hazard if len(mp.SuggestedMeasureIDs) > 0 { hazardPatternMeasures[hz.ID] = mp.SuggestedMeasureIDs }