From 708c61e50d74c75c86b95f9c1c888663d418c5c9 Mon Sep 17 00:00:00 2001 From: Benjamin Admin Date: Thu, 14 May 2026 23:45:41 +0200 Subject: [PATCH] =?UTF-8?q?fix(iace):=20max=205=20mitigations=20per=20haza?= =?UTF-8?q?rd=20=E2=80=94=20clean=20per-hazard=20assignment?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaced category-broadcast logic with per-hazard loop: each hazard gets up to 5 measures (pattern-suggested first, then category fallback). Expected: 108 × 5 = max 540 total. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../api/handlers/iace_handler_init.go | 93 +++++++++---------- 1 file changed, 46 insertions(+), 47 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 798b3eca..358f10a3 100644 --- a/ai-compliance-sdk/internal/api/handlers/iace_handler_init.go +++ b/ai-compliance-sdk/internal/api/handlers/iace_handler_init.go @@ -253,67 +253,66 @@ func (h *IACEHandler) InitializeProject(c *gin.Context) { } created := 0 + const maxMitigationsPerHazard = 5 - // Assign suggested measures to ALL hazards in matching category + // Build a flat list of all hazard IDs for iteration + var allHazardIDs []uuid.UUID + hazardCatByID := make(map[uuid.UUID]string) + for cat, ids := range hazardIDsByCategory { + for _, id := range ids { + allHazardIDs = append(allHazardIDs, id) + hazardCatByID[id] = cat + } + } + + // For each hazard: assign up to maxMitigationsPerHazard measures + // Priority: pattern-suggested first, then category fallback + suggestedByMeasCat := make(map[string][]iace.ProtectiveMeasureEntry) for _, sm := range matchOutput.SuggestedMeasures { - entry, ok := measureByID[sm.MeasureID] - if !ok { - continue + if entry, ok := measureByID[sm.MeasureID]; ok { + suggestedByMeasCat[entry.HazardCategory] = append(suggestedByMeasCat[entry.HazardCategory], entry) } - hazardIDs := findHazardsForMeasureByCategory(entry.HazardCategory, hazardIDsByCategory) - rt := iace.ReductionType(entry.ReductionType) - if rt == "" { - rt = iace.ReductionTypeInformation - } - for _, hazID := range hazardIDs { + } + + for _, hazID := range allHazardIDs { + hazCat := hazardCatByID[hazID] + measCat := patternCatToMeasureCat(hazCat) + added := 0 + + // First: pattern-suggested measures for this category + for _, entry := range suggestedByMeasCat[measCat] { + if added >= maxMitigationsPerHazard { + break + } + rt := iace.ReductionType(entry.ReductionType) + if rt == "" { + rt = iace.ReductionTypeInformation + } _, cerr := h.store.CreateMitigation(ctx, iace.CreateMitigationRequest{ HazardID: hazID, ReductionType: rt, Name: entry.Name, Description: entry.Description, }) if cerr == nil { created++ + added++ } } - } - // Fallback: assign category-based measures only to hazards that - // didn't get any measures from pattern suggestions (max 3 per hazard) - hazardsWithMeasures := make(map[uuid.UUID]bool) - for _, sm := range matchOutput.SuggestedMeasures { - entry, ok := measureByID[sm.MeasureID] - if !ok { - continue - } - for _, ids := range hazardIDsByCategory { - for _, id := range ids { - _ = entry // suppress unused - hazardsWithMeasures[id] = true + // Then: category fallback if still under limit + for _, m := range measuresByCat[measCat] { + if added >= maxMitigationsPerHazard { + break } - } - } - for hazCat, hazIDs := range hazardIDsByCategory { - measCat := patternCatToMeasureCat(hazCat) - measures := measuresByCat[measCat] - for _, hazID := range hazIDs { - if hazardsWithMeasures[hazID] { - continue // Already has pattern-suggested measures + rt := iace.ReductionType(m.ReductionType) + if rt == "" { + rt = iace.ReductionTypeInformation } - added := 0 - for _, m := range measures { - if added >= 3 { - break - } - rt := iace.ReductionType(m.ReductionType) - if rt == "" { - rt = iace.ReductionTypeInformation - } - _, cerr := h.store.CreateMitigation(ctx, iace.CreateMitigationRequest{ - HazardID: hazID, ReductionType: rt, - Name: m.Name, Description: m.Description, - }) - if cerr == nil { - created++ - } + _, cerr := h.store.CreateMitigation(ctx, iace.CreateMitigationRequest{ + HazardID: hazID, ReductionType: rt, + Name: m.Name, Description: m.Description, + }) + if cerr == nil { + created++ added++ } }