diff --git a/ai-compliance-sdk/internal/iace/gt_warewashing_test.go b/ai-compliance-sdk/internal/iace/gt_warewashing_test.go index 1d0a6552..6644bd36 100644 --- a/ai-compliance-sdk/internal/iace/gt_warewashing_test.go +++ b/ai-compliance-sdk/internal/iace/gt_warewashing_test.go @@ -27,7 +27,12 @@ const warewashingNarrative = `Gewerbliche Untertisch-Geschirrspuelmaschine fuer `PIN-geschuetzter Servicetechniker-Fernzugriff. Cool-Ausfuehrung mit kalter Nachspuelung. ` + `Untertischmontage. Eingreifen in die Spuelkammer moeglich. Aerosole und Daempfe der ` + `Reinigungschemie gelangen in die Atemzone. Manuelles Be- und Entladen der Spuelkoerbe von Hand. ` + - `Reinigung und Wartung durch Servicetechniker. Branche Lebensmittel und Getraenke.` + `Reinigung und Wartung durch Servicetechniker. Branche Lebensmittel und Getraenke. ` + + `Siebe und scharfe Blechkanten in der Spuelkammer. Boiler kann bei Wassermangel trockenlaufen. ` + + `Frequenzumrichter und Elektronik mit Restspannung nach dem Abschalten. Wartung nur im ` + + `freigeschalteten Zustand; Gefahr des unerwarteten Wiederanlaufs. Frischwasseranschluss mit ` + + `Rueckflussverhinderer gegen Ruecksaugen in das Trinkwassernetz. Stehwasser im Boiler ` + + `(Hygiene/Legionellen). Standsicherheit bei Untertischmontage.` // warewashingCyberCategories mirrors handlers.nativeCyberSecurityCategories — // native cyber/AI hazards are routed to the CRA module, not the CE hazard log. @@ -134,6 +139,26 @@ func TestWarewashing_GTCoverage(t *testing.T) { t.Logf(" MISS %s: %s", m.Nr, abbrev(m.HazardType, 60)) } } + + // Measure completeness: which generated hazards have NO protective measure? + t.Logf("--- Measure completeness ---") + t.Logf("Measure coverage (GT-matched): %.0f%%", result.MeasureCoverage*100) + withMeas := make(map[string]bool) + for _, m := range mitigations { + withMeas[m.HazardID.String()] = true + } + noMeasure := 0 + for _, h := range hazards { + if !withMeas[h.ID.String()] { + noMeasure++ + n := h.Name + if n == "" { + n = h.Scenario + } + t.Logf(" NO-MEASURE: [%s] %s", h.Category, abbrev(n, 60)) + } + } + t.Logf("Hazards without any measure: %d/%d", noMeasure, len(hazards)) if len(result.ExtraInEngine) > 0 { t.Logf("--- EXTRA (false positives / precision loss) ---") names := make([]string, 0, len(result.ExtraInEngine)) diff --git a/ai-compliance-sdk/internal/iace/pattern_domain_gates.go b/ai-compliance-sdk/internal/iace/pattern_domain_gates.go index 5ba2b582..834d0f5a 100644 --- a/ai-compliance-sdk/internal/iace/pattern_domain_gates.go +++ b/ai-compliance-sdk/internal/iace/pattern_domain_gates.go @@ -67,6 +67,7 @@ var domainGateTerms = map[string]string{ "gondel": "dom_wind", "rotorblatt": "dom_wind", "windenergieanlage": "dom_wind", // CNC / Zerspanung "drehmaschine": "dom_cnc", "fraesmaschine": "dom_cnc", + "spanende": "dom_cnc", "spanenden bearbeitung": "dom_cnc", // Landwirtschaft "maehdrescher": "dom_agri", "ballenpresse": "dom_agri", "feldhaecksler": "dom_agri", // Roll-/Fahrtreppe diff --git a/ai-compliance-sdk/internal/iace/testdata/ground_truth_warewashing.json b/ai-compliance-sdk/internal/iace/testdata/ground_truth_warewashing.json index 3c050083..11d5ebda 100644 --- a/ai-compliance-sdk/internal/iace/testdata/ground_truth_warewashing.json +++ b/ai-compliance-sdk/internal/iace/testdata/ground_truth_warewashing.json @@ -258,6 +258,126 @@ "risk_out": {"f": 1, "w": 1, "p": 1, "s": 2, "r": 4}, "norm_references": ["EN ISO 14120"], "sufficient": true + }, + { + "nr": "1.4", + "hazard_group": "Thermische Gefährdungen", + "hazard_group_applicable": true, + "hazard_type": "Trockenlauf-Überhitzung von Boiler/Heizung", + "hazard_cause": "Das Heizelement bzw. der Boiler läuft bei Wassermangel trocken, überhitzt und kann einen Brand oder eine Verbrühung durch überhitztes Wasser auslösen", + "lifecycle_phases": ["Betrieb"], + "component_zone": "Boiler, Tankheizkörper, Heizelement", + "risk_in": {"f": 2, "w": 2, "p": 2, "s": 3, "r": 18}, + "measures": ["Trockengehschutz / Niveauüberwachung der Heizung", "Temperaturbegrenzer (STB)"], + "measure_type": "KM", + "risk_out": {"f": 1, "w": 1, "p": 1, "s": 3, "r": 9}, + "norm_references": ["EN 60335-2-58", "EN 60335-1"], + "sufficient": true + }, + { + "nr": "3.4", + "hazard_group": "Elektrische Gefährdungen", + "hazard_group_applicable": true, + "hazard_type": "Restspannung / gespeicherte elektrische Energie nach Abschalten", + "hazard_cause": "Nach dem Abschalten der Spannungsversorgung stehen durch Kondensatoren im Frequenzumrichter oder Netzfilter noch gefährliche Berührungsspannungen an", + "lifecycle_phases": ["Instandhaltung", "Fehlersuche und -beseitigung"], + "component_zone": "Frequenzumrichter, Netzfilter, Schaltschrank", + "risk_in": {"f": 1, "w": 2, "p": 3, "s": 4, "r": 24}, + "measures": ["Sichere Energieentladung nach Abschalten", "Warnhinweis Restspannung, Entladezeit abwarten"], + "measure_type": "KM", + "risk_out": {"f": 1, "w": 1, "p": 1, "s": 4, "r": 12}, + "norm_references": ["IEC 60204-1"], + "sufficient": true + }, + { + "nr": "4.6", + "hazard_group": "Mechanische Gefährdungen", + "hazard_group_applicable": true, + "hazard_type": "Schnittverletzung an scharfen Kanten", + "hazard_cause": "Schneiden an scharfen Blechkanten, Sieben oder dem Ablaufpumpen-Laufrad beim Reinigen oder Eingreifen in die Spülkammer", + "lifecycle_phases": ["Reinigung", "Instandhaltung"], + "component_zone": "Zugängliche Kanten, Siebe, Spülkammer, Ablaufpumpe", + "risk_in": {"f": 3, "w": 2, "p": 2, "s": 1, "r": 7}, + "measures": ["Brechen oder Runden aller zugänglichen Kanten"], + "measure_type": "KM", + "risk_out": {"f": 1, "w": 1, "p": 1, "s": 1, "r": 3}, + "norm_references": ["EN ISO 12100"], + "sufficient": true + }, + { + "nr": "4.7", + "hazard_group": "Mechanische Gefährdungen", + "hazard_group_applicable": true, + "hazard_type": "Kippen / mangelnde Standsicherheit", + "hazard_cause": "Unzureichende Standsicherheit bei Untertischmontage, Transport oder Installation führt zum Kippen oder Umstürzen der Maschine", + "lifecycle_phases": ["Transport", "Montage und Installation"], + "component_zone": "Gesamte Maschine, Aufstellbereich", + "risk_in": {"f": 1, "w": 1, "p": 2, "s": 2, "r": 8}, + "measures": ["Standsichere Aufstellung / Befestigung", "Kippsichere Konstruktion"], + "measure_type": "KM", + "risk_out": {"f": 1, "w": 1, "p": 1, "s": 2, "r": 4}, + "norm_references": ["EN ISO 12100"], + "sufficient": true + }, + { + "nr": "2.3", + "hazard_group": "Gefährdungen durch Materialien und Substanzen", + "hazard_group_applicable": true, + "hazard_type": "Rückfluss / Kontamination des Trinkwassers", + "hazard_cause": "Verschmutztes Spül- oder Chemiewasser wird ohne Rückflussverhinderer in das Trinkwassernetz zurückgesaugt und kontaminiert es", + "lifecycle_phases": ["Betrieb"], + "component_zone": "Frischwasseranschluss, Wasserzulauf", + "risk_in": {"f": 2, "w": 2, "p": 2, "s": 3, "r": 18}, + "measures": ["Rückflussverhinderer / Systemtrenner nach EN 1717", "Freier Auslauf"], + "measure_type": "KM", + "risk_out": {"f": 1, "w": 1, "p": 1, "s": 3, "r": 9}, + "norm_references": ["EN 1717", "EN 60335-2-58"], + "sufficient": true + }, + { + "nr": "2.4", + "hazard_group": "Gefährdungen durch Materialien und Substanzen", + "hazard_group_applicable": true, + "hazard_type": "Mikrobielle Belastung / Legionellen im Stehwasser", + "hazard_cause": "Stehwasser im Boiler oder Tank bei niedrigen Temperaturen begünstigt mikrobielles Wachstum und Legionellen, die über Aerosole eingeatmet werden", + "lifecycle_phases": ["Betrieb", "Instandhaltung"], + "component_zone": "Boiler, Tank, Stehwasser", + "risk_in": {"f": 1, "w": 1, "p": 2, "s": 3, "r": 12}, + "measures": ["Thermische Desinfektion / ausreichende Wassertemperatur", "Regelmäßiger Wasserwechsel"], + "measure_type": "KM", + "risk_out": {"f": 1, "w": 1, "p": 1, "s": 3, "r": 9}, + "norm_references": ["EN 60335-2-58"], + "sufficient": true + }, + { + "nr": "6.3", + "hazard_group": "zusätzliche Gefährdungen", + "hazard_group_applicable": true, + "hazard_type": "Versagen der Tür-/Schutzeinrichtungs-Verriegelung", + "hazard_cause": "Die Verriegelung des Tür-Sicherheitsschalters versagt oder wird überbrückt, sodass der Zugriff in die Spülkammer bei laufendem Spülgang (Heißwasser, rotierender Spülarm) möglich wird", + "lifecycle_phases": ["Betrieb", "Instandhaltung"], + "component_zone": "Tür-Sicherheitsschalter, Verriegelung, Spülkammer", + "risk_in": {"f": 3, "w": 2, "p": 2, "s": 3, "r": 21}, + "measures": ["Sichere Verriegelung mit Fehlerüberwachung (PL nach ISO 13849)", "Zwangsöffnende Kontakte"], + "measure_type": "KM", + "risk_out": {"f": 1, "w": 1, "p": 1, "s": 3, "r": 9}, + "norm_references": ["EN ISO 14119", "EN ISO 13849-1"], + "sufficient": true + }, + { + "nr": "6.4", + "hazard_group": "zusätzliche Gefährdungen", + "hazard_group_applicable": true, + "hazard_type": "Unerwarteter Wiederanlauf bei Wartung", + "hazard_cause": "Während Wartung oder Reinigung läuft die Maschine durch fehlende Freischaltung (LOTO) oder automatischen Wiederanlauf unerwartet an", + "lifecycle_phases": ["Instandhaltung", "Reinigung"], + "component_zone": "Gesamte Maschine, Antriebe, Pumpe", + "risk_in": {"f": 2, "w": 2, "p": 2, "s": 3, "r": 18}, + "measures": ["Freischalten und gegen Wiedereinschalten sichern (LOTO)", "Kein automatischer Wiederanlauf"], + "measure_type": "KM", + "risk_out": {"f": 1, "w": 1, "p": 1, "s": 3, "r": 9}, + "norm_references": ["IEC 60204-1", "EN ISO 12100"], + "sufficient": true } ] }