diff --git a/ai-compliance-sdk/internal/iace/hazard_patterns_lift_endstop.go b/ai-compliance-sdk/internal/iace/hazard_patterns_lift_endstop.go new file mode 100644 index 00000000..85304009 --- /dev/null +++ b/ai-compliance-sdk/internal/iace/hazard_patterns_lift_endstop.go @@ -0,0 +1,96 @@ +package iace + +// Body-part-specific crush hazards at lift / hoist / scissor-lift endstops. +// Bridges the gap that the Kistenhubgeraet re-init exposed: the abstract +// "Bremse versagt bei Absenkbewegung" pattern fires, but the concrete +// "Fuss unter absenkender Hubplattform" body-part variant did not exist. +// +// Each pattern restricts to lift-family machine types via MachineTypes, +// so a press / CNC / textile project does not pick them up. Mitigations +// reference the new M600-M604 (lift endstop) library plus the existing +// M001 (geometry), M002 (safety distance), M141 (warning sign). + +func GetLiftEndstopPatterns() []HazardPattern { + liftTypes := []string{"lift", "hoist", "elevator", "scissor_lift"} + return []HazardPattern{ + { + ID: "HP2100", + NameDE: "Fuss-Quetschung unter absenkender Hubplattform am Bodenanschlag", + NameEN: "Foot crush under descending lift platform at floor stop", + RequiredComponentTags: []string{"crush_point", "gravity_risk", "person_under_load"}, + RequiredEnergyTags: []string{"gravitational"}, + MachineTypes: liftTypes, + GeneratedHazardCats: []string{"mechanical_hazard"}, + SuggestedMeasureIDs: []string{"M600", "M601", "M604", "M141"}, + Priority: 92, + ScenarioDE: "Fuss oder Bein des Bedieners gelangt waehrend des Absenkvorgangs unter die " + + "Hubplattform. Bei Erreichen der unteren Endlage wird der Fuss zwischen Plattform " + + "und Boden gequetscht.", + TriggerDE: "Unsachgemaesse Position des Bedieners beim Be-/Entladen, fehlende Schaltleiste, fehlender Trittschutz", + HarmDE: "Fussquetschung, Mittelfussfraktur, Zehenamputation", + AffectedDE: "Bediener, Wartungspersonal", + ZoneDE: "Bodenbereich unter Hubplattform, umlaufende Spalte", + DefaultSeverity: 4, + DefaultExposure: 3, + DefaultAvoidability: 2, + ISO12100Section: "6.3.5.5 Quetschen — Mindestabstaende", + ClarificationQuestionsDE: []string{ + "Ist eine umlaufende Quetsch-Schaltleiste an der Plattformunterkante verbaut?", + "Ist die Hubgeschwindigkeit am unteren Endanschlag auf <=15 mm/s reduziert (siehe M600)?", + "Verhindert ein Trittblech / Unterfahrschutz das Hineinfahren von Fuessen?", + }, + }, + { + ID: "HP2101", + NameDE: "Hand- oder Koerper-Quetschung gegen feste Struktur beim Hochfahren der Hubeinheit", + NameEN: "Hand or body crush against fixed structure during lift upward travel", + RequiredComponentTags: []string{"crush_point", "gravity_risk"}, + RequiredEnergyTags: []string{"gravitational"}, + MachineTypes: liftTypes, + GeneratedHazardCats: []string{"mechanical_hazard"}, + SuggestedMeasureIDs: []string{"M602", "M603", "M600", "M141"}, + Priority: 90, + ScenarioDE: "Beim Hochfahren der Last gelangen Hand oder Koerperteile des Bedieners " + + "zwischen die hoechste Position der Hubeinheit (z.B. mit beladener Palette) und " + + "eine feste Struktur oberhalb (Decke, Vorbau, Querbalken einer umschliessenden Anlage).", + TriggerDE: "Eingriff in den Verfahrweg waehrend Hubvorgang, fehlende konstruktive Begrenzung der Endlage", + HarmDE: "Hand- oder Armquetschung, im Extremfall Brustkorbkompression", + AffectedDE: "Bediener, Einrichter, Wartungspersonal", + ZoneDE: "Oberhalb hoechster Hubposition, Vorbau/Decke der umschliessenden Anlage", + DefaultSeverity: 4, + DefaultExposure: 2, + DefaultAvoidability: 2, + ISO12100Section: "6.3.5.5 Quetschen — Mindestabstaende", + ClarificationQuestionsDE: []string{ + "Welcher Mindestabstand zu festen Strukturen oberhalb der hoechsten Hubposition ist gegeben? (Empfehlung: 120 mm fuer Kopf, 100 mm fuer Hand)", + "Ist der Tippbetrieb (Hold-to-run) durch ein Testprotokoll mit Stop-Zeit-Messung verifiziert?", + "Existiert eine redundante Hardware-Endlage zusaetzlich zur Software-Begrenzung?", + }, + }, + { + ID: "HP2102", + NameDE: "Quetschung Bein/Koerper zwischen Hubeinheit und seitlicher Struktur", + NameEN: "Leg/body crush between lift unit and lateral structure", + RequiredComponentTags: []string{"crush_point", "gravity_risk", "moving_part"}, + RequiredEnergyTags: []string{"gravitational"}, + MachineTypes: liftTypes, + GeneratedHazardCats: []string{"mechanical_hazard"}, + SuggestedMeasureIDs: []string{"M602", "M601", "M141"}, + Priority: 85, + ScenarioDE: "Person befindet sich seitlich neben der Hubeinheit und wird waehrend " + + "der Bewegung gegen eine feste Struktur (Regalwand, Stuetze, andere Anlage) gequetscht.", + TriggerDE: "Aufenthalt in Quetschzone bei Bewegung, fehlende Absperrung", + HarmDE: "Beinfraktur, Beckenquetschung", + AffectedDE: "Bediener, vorbeigehende Personen", + ZoneDE: "Seitlicher Bereich neben Hubeinheit, Lichte Weite zu festen Strukturen", + DefaultSeverity: 4, + DefaultExposure: 2, + DefaultAvoidability: 2, + ISO12100Section: "6.3.5.5 Quetschen — Mindestabstaende", + ClarificationQuestionsDE: []string{ + "Welcher Sicherheitsabstand zu seitlichen festen Strukturen ist gegeben (Empfehlung 500 mm Koerperdurchgang)?", + "Ist der Bereich seitlich der Hubeinheit als Gefahrenzone markiert oder abgeschrankt?", + }, + }, + } +} diff --git a/ai-compliance-sdk/internal/iace/measures_library.go b/ai-compliance-sdk/internal/iace/measures_library.go index 40a0cece..4de0919d 100644 --- a/ai-compliance-sdk/internal/iace/measures_library.go +++ b/ai-compliance-sdk/internal/iace/measures_library.go @@ -21,6 +21,7 @@ func GetProtectiveMeasureLibrary() []ProtectiveMeasureEntry { all = append(all, GetTextileAgriMeasures()...) // Textil + Landmaschinen (Phase 5) all = append(all, getGTBremseMeasures()...) // GT-Bremse-Coverage-Gaps (M483-M522) all = append(all, GetCRAMeasures()...) // CRA / DIN EN 40000-1-2 cyber-resilience (M540-M548) + all = append(all, getLiftEndstopMeasures()...) // Lift/hoist endstop (M600-M604) — bridges OSHA MD library return all } diff --git a/ai-compliance-sdk/internal/iace/measures_library_lift_endstop.go b/ai-compliance-sdk/internal/iace/measures_library_lift_endstop.go new file mode 100644 index 00000000..00ff4840 --- /dev/null +++ b/ai-compliance-sdk/internal/iace/measures_library_lift_endstop.go @@ -0,0 +1,134 @@ +package iace + +// Lift / hoist / scissor-lift endstop mitigations — bridges the OSHA +// minimum-distance library (minimum_distances.go, Task #18) into the +// pattern-engine measure library. Each entry cites the concrete OSHA +// value AND its EU-norm pendant by identifier only. +// +// Engineering rounding values come from MD_OSHA_* IDs in +// minimum_distances.go. We do not duplicate the source text here — +// the Tech-File renderer can join MD_OSHA_* into the rendered text +// at output time. + +func getLiftEndstopMeasures() []ProtectiveMeasureEntry { + return []ProtectiveMeasureEntry{ + // M600 — Cruise/creep speed at end of travel + { + ID: "M600", + ReductionType: "protection", + SubType: "speed_control", + Name: "Kriechgeschwindigkeit am Endanschlag (Hubgeraete)", + Description: "Hubgeschwindigkeit am Ende der Verfahrbewegung (oben und unten) auf maximal 15 mm/s " + + "reduzieren. OSHA 29 CFR 1910.217 Hand-Speed-Konstante 63 in/s = 1.600 mm/s als Obergrenze " + + "fuer Stopp-Reaktionszeit. Damit ist auch bei spaeter Auslosung der Quetsch-Schaltleiste " + + "genug Bremsweg vorhanden.", + HazardCategory: "mechanical", + Examples: []string{ + "Hub-Endschalter mit Soft-Stop und Geschwindigkeitsstufe < 15 mm/s in den letzten 50 mm", + "Servo-Antrieb mit Ramp-down-Profil ueber die letzten 100 mm Verfahrweg", + "Drehzahl-Begrenzer im Frequenzumrichter mit Endlagen-Trigger", + }, + NormReferences: []string{ + "OSHA 29 CFR 1910.217 (Ds = 63 in/s x Ts)", + "EN ISO 13855 (Anordnung von Schutzeinrichtungen)", + "EN 1570-1 (Hubtische — Bauanforderungen)", + }, + RiskReduction: &RiskReduction{SeverityDelta: -1, ExposureDelta: -1, ProbabilityDelta: -1}, + Tags: []string{"crush_point", "gravity_risk", "speed_limit"}, + }, + // M601 — Trip-edge sensor under platform (safety bumper) + { + ID: "M601", + ReductionType: "protection", + SubType: "safety_device", + Name: "Quetsch-Schaltleiste unterhalb der Hubplattform", + Description: "Druckempfindliche Schaltleiste (gemaess EN ISO 13856-2) am unteren Rand der Hubplattform " + + "loest bei Beruehrung den Hubantrieb sofort aus und kehrt die Bewegung um. Verhindert Quetschung " + + "von Fuessen oder Beinen unter absenkender Last. PL c oder hoeher nach EN ISO 13849-1.", + HazardCategory: "mechanical", + Examples: []string{ + "Schaltleiste umlaufend an Bodenkante der Hubplattform", + "Trittschutz mit redundanter Auswertung am Hubtisch", + "Lichtgitter im Bodenbereich als Ergaenzung bei freistehenden Anlagen", + }, + NormReferences: []string{ + "EN ISO 13856-2 (Schaltleisten)", + "EN ISO 13849-1 (PL-Bestimmung)", + "EN 1570-1", + }, + RiskReduction: &RiskReduction{SeverityDelta: -2, ExposureDelta: -2, ProbabilityDelta: -2}, + Tags: []string{"crush_point", "gravity_risk", "safety_device"}, + }, + // M602 — Minimum clearance to fixed structure above max lift position + { + ID: "M602", + ReductionType: "design", + SubType: "geometry", + Name: "Mindestabstand zu festen Strukturen oberhalb der Hubendlage", + Description: "Zwischen hoechstem Punkt der Hubeinheit (mit beladenem Werkstueck) und festen Strukturen " + + "oberhalb (Decke, Vorbau, Querbalken) muss ein Sicherheitsabstand verbleiben, der das Quetschen " + + "von Haenden und Koerper verhindert. Empfehlung: 120 mm fuer Kopf, 100 mm fuer Hand, 25 mm fuer " + + "Finger — abgeleitet aus EN 349 / EN ISO 13854 unabhaengig zu pruefen.", + HazardCategory: "mechanical", + Examples: []string{ + "Konstruktive Begrenzung der oberen Hubposition durch mechanischen Anschlag", + "Software-Endlage mit redundantem Hardware-Sicherheitsschalter", + "Auslegungs-Pruefung mit beladener Standard-Palette und Maximal-Hubhoehe", + }, + NormReferences: []string{ + "EN 349 (Mindestabstaende gegen Quetschen von Koerperteilen)", + "EN ISO 13854 (Mindestabstaende gegen Quetschen)", + "OSHA 29 CFR 1910.212(a)(5) (Lueftergitter ≤ 1/2 in als Anker)", + }, + RiskReduction: &RiskReduction{SeverityDelta: -2, ExposureDelta: -1}, + Tags: []string{"crush_point", "gravity_risk"}, + }, + // M603 — Hold-to-run with two-hand operation for manual descent + { + ID: "M603", + ReductionType: "protection", + SubType: "control_device", + Name: "Tippbetrieb / Hold-to-run beim Absenken (mit Verifikations-Nachweis)", + Description: "Absenken nur im Tippbetrieb (Hold-to-run): Bedientaster muss waehrend des gesamten " + + "Absenkvorgangs gedrueckt gehalten werden. Bei Loslassen stoppt die Bewegung sofort. " + + "Im Limits-Form als 'Tippbetrieb' deklariert — durch Tests verifizieren (Stop-Reaktionszeit " + + "<= 0,3 s im voll beladenen Zustand).", + HazardCategory: "mechanical", + Examples: []string{ + "Tipptaster mit elektrischer Selbstrueckstellung", + "Zweihand-Bedienung fuer kritische Absenk-Bereiche (Tipp + Zustimmtaster)", + "Pruefprotokoll Stop-Zeit gemaess EN ISO 13849-1 PL c", + }, + NormReferences: []string{ + "EN ISO 13849-1 (Sicherheitsbezogene Steuerungsteile)", + "EN ISO 13851 (Zweihandschaltungen)", + "BetrSichV § 4 (Schutzmassnahmen)", + }, + RiskReduction: &RiskReduction{SeverityDelta: -1, ExposureDelta: -2, ProbabilityDelta: -1}, + Tags: []string{"crush_point", "gravity_risk", "control_device"}, + }, + // M604 — Underrun guard / kick plate at platform base + { + ID: "M604", + ReductionType: "design", + SubType: "geometry", + Name: "Trittblech / Unterfahrschutz an der Hubplattform", + Description: "Unter der Hubplattform befindet sich ein umlaufendes Trittblech oder Unterfahrschutz, " + + "das das Hineinfahren von Fuessen unter die Plattform mechanisch verhindert. Hoehe ueber Boden " + + "maximal 5 mm in unterster Stellung. Trittblech haelt die Last eines Schuhs (mind. 150 kg) " + + "ohne Verformung.", + HazardCategory: "mechanical", + Examples: []string{ + "Umlaufendes Stahlblech 3 mm Wandstaerke mit Fasen-Kante", + "Kombination mit M601 (Schaltleiste) als doppelte Sicherung", + "Pruefung jaehrlich auf Verformung und Funktion der Auflage", + }, + NormReferences: []string{ + "EN 1570-1 (Hubtische)", + "EN ISO 13857 (Sicherheitsabstaende)", + }, + RiskReduction: &RiskReduction{SeverityDelta: -2, ExposureDelta: -1}, + Tags: []string{"crush_point", "gravity_risk"}, + }, + } +} diff --git a/ai-compliance-sdk/internal/iace/pattern_machinetype_overrides.go b/ai-compliance-sdk/internal/iace/pattern_machinetype_overrides.go new file mode 100644 index 00000000..491afe2f --- /dev/null +++ b/ai-compliance-sdk/internal/iace/pattern_machinetype_overrides.go @@ -0,0 +1,60 @@ +package iace + +// Machine-type overrides for legacy patterns that lacked MachineTypes +// filtering at authoring time. Applied as a post-load pass in +// collectAllPatterns() so we do not need to touch the large pattern +// source files (which would push them past the 500-LOC cap). +// +// Adding an entry here causes the listed pattern IDs to fire ONLY for +// projects whose machine_type is in the value list. This eliminates +// drift like "Punktschweisselektroden" firing for a Kistenhubgeraet +// project just because tags incidentally aligned. + +var legacyMachineTypeOverrides = map[string][]string{ + // Walzen / Roller hazards — printing, paper, metalworking only. + "HP1000": {"printing", "paper", "textile", "metalworking", "rolling_mill", "food_processing"}, + // HP306 + HP1530 already carry MachineTypes; skip. + + // Welding-specific patterns. + "HP539": {"welding", "spot_welding"}, + + // Glass-handling tilters. + "HP545": {"glass", "glass_processing"}, + "HP782": {"glass", "glass_processing"}, + + // Escalator-specific. + "HP756": {"escalator"}, + "HP757": {"escalator"}, + "HP760": {"escalator"}, + + // CNC machine tools (these fired on Kistenhubgeraet because they + // share crush_point + moving_part tags but are bench-mounted tools). + "HP1400": {"cnc", "metalworking", "lathe", "milling"}, + "HP1401": {"cnc", "metalworking", "lathe", "milling"}, + "HP1402": {"cnc", "metalworking", "lathe", "milling"}, + + // Press-specific (Pressenteile/Pressraum/Werkzeugraum). + "HP045": {"press", "hydraulic_press", "mechanical_press", "stamping_press"}, + "HP049": {"press", "hydraulic_press", "mechanical_press", "stamping_press"}, + + // Conveyor-belt-specific drift. + "HP420": {"conveyor", "packaging", "food_processing"}, + "HP421": {"conveyor", "packaging", "food_processing"}, + "HP422": {"conveyor", "packaging", "food_processing"}, +} + +// applyMachineTypeOverrides mutates the passed slice in place, setting +// MachineTypes on any pattern whose ID is in the override map. Patterns +// that already have MachineTypes set are NOT overwritten — the override +// only fills the gap. +func applyMachineTypeOverrides(patterns []HazardPattern) []HazardPattern { + for i := range patterns { + if len(patterns[i].MachineTypes) > 0 { + continue + } + if mt, ok := legacyMachineTypeOverrides[patterns[i].ID]; ok { + patterns[i].MachineTypes = mt + } + } + return patterns +} diff --git a/ai-compliance-sdk/internal/iace/pattern_registry.go b/ai-compliance-sdk/internal/iace/pattern_registry.go index 0b7c4e95..a2c78c4f 100644 --- a/ai-compliance-sdk/internal/iace/pattern_registry.go +++ b/ai-compliance-sdk/internal/iace/pattern_registry.go @@ -43,5 +43,7 @@ func collectAllPatterns() []HazardPattern { patterns = append(patterns, GetISO12100GapPatterns()...) // HP1900-HP1909 ISO 12100 Annex B gaps (Vakuum, Federn, Rutsch, Hochdruckinjektion, Ersticken) patterns = append(patterns, GetCRAPatterns()...) // HP1910-HP1918 CRA / DIN EN 40000-1-2 cyber-resilience spur patterns = append(patterns, GetSecondaryHarmDemoPatterns()...) // HP2000-HP2001 secondary harm chain demos (Cola splitter, Pharma) + patterns = append(patterns, GetLiftEndstopPatterns()...) // HP2100-HP2102 lift body-part crush at endstops + patterns = applyMachineTypeOverrides(patterns) // Fill MachineTypes on legacy patterns to prevent drift return patterns }