From 5ea68ebea427f8df6977c01b4da0514cc966dd56 Mon Sep 17 00:00:00 2001 From: Benjamin Admin Date: Sat, 16 May 2026 22:23:56 +0200 Subject: [PATCH] feat(iace): clarification questions + HP1632 Bersten + HP1637 KSS-Aerosol fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drei nachhaltige Verbesserungen, getrieben durch die Bremse-Benchmark- Faelle GT 1.4, GT 1.30 und GT 7.4. Die Engine erfindet weiterhin keine Fachmann-Kommentare — Kommentare bleiben aus, weil sie ein Verstaendnis der konkreten Anlage erfordern, das die Engine nicht hat. Statt dessen liefert die Engine norm-basierte Klaerungsfragen und ein praeziseres Pattern-Vokabular. A) HazardPattern.ClarificationQuestionsDE — neues optionales Feld: - Pattern hinterlegt prueffaehige Fragen, die der Bediener mit dem Anlagenbauer abklaert. Beispiele: - HP1640: "Liegt ein Pruefprotokoll nach EN 60204-1 vor?" - HP1666: "Ist die WZM als CE-konformes Subsystem integriert?" - HP1604: "Ist DCS am Roboter konfiguriert und validiert?" - Init-Handler haengt die Fragen an Hazard.Description an mit dem Marker "Mit Anlagenbauer zu klaeren:". Kein DB-Schema-Aenderungs- bedarf. - 11 Patterns mit Klaerungsfragen versehen (HP1602, HP1604, HP1611, HP1612, HP1620, HP1622, HP1637, HP1640, HP1641, HP1666, HP1685). B) HP1632 "Bersten druckbeaufschlagter Pneumatik-Komponente" — neues Pattern, semantisch DISTINKT zu HP1630 "Abspringen": - Bersten = Material-/Druckversagen der Komponente, Mediumaustritt - Abspringen = Verbindung loest sich, Peitscheneffekt Bremse-Benchmark GT 1.4 sprach von Bersten, HP1630 nur von Abspringen — ein 66%-Frontend-Match war eine Sackgasse. Mit HP1632 feuert die Engine ein eigenes Hazard, das auf GT 1.4 einen sauberen Volltreffer liefert. C) HP1637 "Einatmen von KSS-Aerosolen" — Massnahmen vervollstaendigt: Vorher nur M141 (Sicherheitszeichen), neu zusaetzlich M405 (KSS- Aerosolabsaugung), M418 (AGW-Ueberwachung), M526 (WZM-Tueren geschlossen waehrend Bearbeitung), M408 (Hautschutzplan). Klaerungsfrage: "Wurde die Aerosolkonzentration nach Bearbeitungs- ende messtechnisch ermittelt und mit dem AGW verglichen?" Co-Authored-By: Claude Opus 4.7 (1M context) --- .../api/handlers/iace_handler_init.go | 16 ++++++++- .../internal/iace/hazard_pattern_types.go | 12 +++++++ .../iace/hazard_patterns_robot_cell.go | 33 ++++++++++++++++++- .../iace/hazard_patterns_robot_cell_ext.go | 2 ++ .../internal/iace/pattern_engine.go | 6 ++-- 5 files changed, 65 insertions(+), 4 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 3ad99a24..fc1940d3 100644 --- a/ai-compliance-sdk/internal/api/handlers/iace_handler_init.go +++ b/ai-compliance-sdk/internal/api/handlers/iace_handler_init.go @@ -212,11 +212,25 @@ func (h *IACEHandler) InitializeProject(c *gin.Context) { // Join all applicable lifecycles as comma-separated string lifecycleStr := strings.Join(mp.ApplicableLifecycles, ",") + // Append pattern-defined clarification questions to the + // description so they're visible in the UI without DB- + // schema changes. The engine does NOT invent commentary; + // it only hangs the standard ISO/EN clarification points + // onto the hazard so the operator knows what to verify + // with the Anlagenbauer. + desc := mp.ScenarioDE + if len(mp.ClarificationQuestionsDE) > 0 { + desc += "\n\nMit Anlagenbauer zu klaeren:" + for _, q := range mp.ClarificationQuestionsDE { + desc += "\n- " + q + } + } + hz, cerr := h.store.CreateHazard(ctx, iace.CreateHazardRequest{ ProjectID: projectID, ComponentID: compID, Name: name, - Description: mp.ScenarioDE, + Description: desc, Category: cat, Scenario: mp.ScenarioDE, Function: iace.EncodeOpStates(mp.OperationalStates), diff --git a/ai-compliance-sdk/internal/iace/hazard_pattern_types.go b/ai-compliance-sdk/internal/iace/hazard_pattern_types.go index 4781058c..3425ac8a 100644 --- a/ai-compliance-sdk/internal/iace/hazard_pattern_types.go +++ b/ai-compliance-sdk/internal/iace/hazard_pattern_types.go @@ -19,6 +19,18 @@ type HazardPattern struct { RequiresExpertCalculation bool `json:"requires_expert_calculation,omitempty"` ExpertHintDE string `json:"expert_hint_de,omitempty"` ExpertHintEN string `json:"expert_hint_en,omitempty"` + // ClarificationQuestionsDE: konkrete Fragen die der Bediener mit dem + // Anlagenbauer abklaeren sollte, bevor er das Hazard als abgedeckt + // betrachtet. Die Engine erfindet keine Begruendungen, sondern hinter- + // legt nur prueffaehige Fragen aus Norm-Wissen. Beispiele: + // - "Liegt ein Pruefprotokoll nach EN 60204-1 vor?" + // - "Wird die Sicherheitsfunktion durch CE-Konformitaet der + // Subkomponente abgedeckt? (Herstellererklaerung anfordern)" + // - "Ist DCS-Achsbegrenzung am Roboter konfiguriert und validiert?" + // Im Init-Handler werden diese Fragen an die Hazard.Description + // angehaengt mit einem klaren Trenner — kein DB-Schema-Aenderungs- + // bedarf. + ClarificationQuestionsDE []string `json:"clarification_questions_de,omitempty"` // Detail fields — populated into Hazard DB when pattern fires ScenarioDE string `json:"scenario_de,omitempty"` // Gefahrensituation TriggerDE string `json:"trigger_de,omitempty"` // Gefaehrdendes Ereignis diff --git a/ai-compliance-sdk/internal/iace/hazard_patterns_robot_cell.go b/ai-compliance-sdk/internal/iace/hazard_patterns_robot_cell.go index 9cc9b01b..3bc77b27 100644 --- a/ai-compliance-sdk/internal/iace/hazard_patterns_robot_cell.go +++ b/ai-compliance-sdk/internal/iace/hazard_patterns_robot_cell.go @@ -38,6 +38,7 @@ func GetRobotCellPatterns() []HazardPattern { HarmDE: "Quetschung von Hand oder Arm zwischen Roboterarm und feststehenden Teilen.", AffectedDE: "Bedienpersonal, Reinigungspersonal", ZoneDE: "Schutzzaun-Oberkante, Roboterarm", + ClarificationQuestionsDE: []string{"Ist Dynamic Safety Configuration (DCS) am Roboter konfiguriert und durch den Hersteller validiert?", "Wurde der Reach-Over-Sicherheitsabstand nach EN ISO 13857 anlagenbezogen berechnet?"}, DefaultSeverity: 3, DefaultExposure: 2, }, { @@ -66,6 +67,7 @@ func GetRobotCellPatterns() []HazardPattern { HarmDE: "Teile des Schutzzauns werden herausgeschleudert, Person ausserhalb wird getroffen.", AffectedDE: "Bedienpersonal in der Naehe des Schutzzauns", ZoneDE: "Schutzzaun, Bereich um die Roboterzelle", + ClarificationQuestionsDE: []string{"Ist Dynamic Safety Configuration (DCS) am Roboter konfiguriert und durch den Hersteller validiert?", "Ist nach EN ISO 13857 die Tabelle 1 (Niedrigrisiko) anwendbar oder muss Tabelle 2 angewandt werden?"}, DefaultSeverity: 3, DefaultExposure: 2, }, { @@ -111,6 +113,7 @@ func GetRobotCellPatterns() []HazardPattern { HarmDE: "Prellungen, Knochenbrueche abhaengig von Werkstueckgewicht und Fallhoehe.", AffectedDE: "Bedienpersonal, Wartungspersonal", ZoneDE: "Bereich unterhalb des Greifer/Roboterarms", + ClarificationQuestionsDE: []string{"Welche Druckhalte-Logik ist am Greifer realisiert? (Empfehlung: 5-3 Wegeventil mit Sperrmittelstellung, auch bei Not-Halt)", "Ist nachgewiesen, dass das Werkstueck bei Spannungs- oder Druckluftausfall sicher gehalten wird (Fail-Safe)?"}, DefaultSeverity: 3, DefaultExposure: 2, }, { @@ -125,6 +128,7 @@ func GetRobotCellPatterns() []HazardPattern { HarmDE: "Person ausserhalb der Zelle wird von weggeschleudertem Werkstueck getroffen.", AffectedDE: "Bedienpersonal in der Naehe der Roboterzelle", ZoneDE: "Schutzzaun, Bereich um die Roboterzelle", + ClarificationQuestionsDE: []string{"Ist die Lastbemessung der Einhausung auf max. Werkstueckgewicht * max. Roboter-TCP-Geschwindigkeit dokumentiert?", "Sind max. Werkstueckgewicht und Roboter-TCP-Geschwindigkeit in der Betriebsanleitung explizit angegeben?"}, DefaultSeverity: 3, DefaultExposure: 2, }, // ================================================================ @@ -142,6 +146,7 @@ func GetRobotCellPatterns() []HazardPattern { HarmDE: "Quetschung von Fingern, Einzug von Kleidung oder Haaren.", AffectedDE: "Bedienpersonal, Reinigungspersonal", ZoneDE: "Foerderbaender, Bandein- und -auslauf", + ClarificationQuestionsDE: []string{"Ist die Bandgeschwindigkeit im manuell zugaenglichen Bereich dokumentiert? (Empfehlung: <= 100 mm/s)", "Sind Quetsch- und Einzugsstellen am Band konstruktiv ausgeschlossen oder durch Lichtschranke gesichert?"}, DefaultSeverity: 2, DefaultExposure: 3, }, { @@ -170,6 +175,7 @@ func GetRobotCellPatterns() []HazardPattern { HarmDE: "Prellungen, Quetschung von Fuessen durch herabfallendes Werkstueck.", AffectedDE: "Bedienpersonal am Be-/Entladeplatz", ZoneDE: "Ende der Transportbaender, Be-/Entladeplatz", + ClarificationQuestionsDE: []string{"Sind mechanische Anschlaege an allen Bandenden vorhanden und auf maximale Werkstueckmasse + Bandgeschwindigkeit dimensioniert?"}, DefaultSeverity: 2, DefaultExposure: 3, }, // ================================================================ @@ -220,6 +226,28 @@ func GetRobotCellPatterns() []HazardPattern { ZoneDE: "Pneumatikschlaeuche und -komponenten", DefaultSeverity: 2, DefaultExposure: 2, }, + // HP1632 (Bersten) ist semantisch DISTINKT zu HP1630 (Abspringen). + // Bersten = Material-/Druckversagen der Komponente, Mediumaustritt. + // Abspringen = Schlauchverbindung loest sich, Peitscheneffekt. + // Beide Patterns feuern parallel und erzeugen zwei eigene Hazards. + { + ID: "HP1632", NameDE: "Bersten druckbeaufschlagter Pneumatik-Komponente", NameEN: "Pressurized pneumatic component bursting", + RequiredComponentTags: []string{"pinch_point"}, + GeneratedHazardCats: []string{"mechanical_hazard"}, + SuggestedMeasureIDs: []string{"M483", "M484", "M485", "M141"}, + Priority: 97, + ApplicableLifecycles: []string{"normal_operation", "setup", "maintenance", "fault_clearing"}, + ScenarioDE: "Druckbeaufschlagte Teile des Pneumatiksystems (Leitungen, Dichtungen, Verbindungsstuecke, Befestigungen) bersten unter Betriebsdruck und verletzen eine Person.", + TriggerDE: "Komponenten sind nicht auf den Anlagen-Nenndruck dimensioniert, Materialermuedung, Ueberdruckereignis.", + HarmDE: "Augen-, Haut- und Stossverletzungen durch berstendes Material und unter Druck austretendes Medium.", + AffectedDE: "Bedienpersonal, Wartungspersonal", + ZoneDE: "Pneumatikkomponenten der Anlage (Leitungen, Dichtungen, Verbindungsstuecke)", + ClarificationQuestionsDE: []string{ + "Sind alle Pneumatik-Komponenten (Leitungen, Dichtungen, Verbindungen) auf den Anlagen-Nenndruck nach EN ISO 4414 ausgelegt?", + "Liegen Berstdrucknachweise der Schlauchhersteller fuer den eingesetzten Druckbereich vor?", + }, + DefaultSeverity: 2, DefaultExposure: 2, + }, // ================================================================ // Kuehlschmierstoff (KSS) // ================================================================ @@ -297,7 +325,7 @@ func GetRobotCellPatterns() []HazardPattern { ID: "HP1637", NameDE: "Einatmen von KSS-Aerosolen", NameEN: "Inhalation of coolant aerosols", RequiredComponentTags: []string{}, GeneratedHazardCats: []string{"material_environmental"}, - SuggestedMeasureIDs: []string{"M141"}, + SuggestedMeasureIDs: []string{"M405", "M418", "M526", "M408", "M141"}, Priority: 97, MachineTypes: []string{"cnc", "metalworking", "automotive"}, ApplicableLifecycles: []string{"normal_operation", "setup", "maintenance"}, ScenarioDE: "Person oeffnet Schutztuer der Bearbeitungszelle und atmet freigesetzte KSS-Aerosole ein.", @@ -305,6 +333,7 @@ func GetRobotCellPatterns() []HazardPattern { HarmDE: "Person atmet KSS-Aerosole ein. Atembeschwerden, Reizung der Atemwege, bei chronischer Exposition Atemwegserkrankungen.", AffectedDE: "Bedienpersonal", ZoneDE: "Bearbeitungszelle, Bereich vor der Schutztuer", + ClarificationQuestionsDE: []string{"Wurde die KSS-Aerosolkonzentration nach Bearbeitungsende messtechnisch ermittelt und mit dem Arbeitsplatzgrenzwert verglichen?", "Erfolgt die Bearbeitung trocken, mit Minimalmengenschmierung oder mit Ueberflutungskuehlung? Die Massnahmen-Auswahl haengt davon ab."}, DefaultSeverity: 1, DefaultExposure: 3, }, // ================================================================ @@ -323,6 +352,7 @@ func GetRobotCellPatterns() []HazardPattern { HarmDE: "Person erleidet elektrischen Schlag. Herzkammerflimmern, Verbrennungen, bei Hochspannung Todesfolge.", AffectedDE: "Wartungspersonal, Einrichter", ZoneDE: "Zugaengliche Kabel, Klemmen, Schaltschrank", + ClarificationQuestionsDE: []string{"Liegt ein Pruefprotokoll nach EN 60204-1 fuer die Niederspannungs-Isolation vor?", "Sind die Schutzart IP2X bzw. IPXXB an allen niederspannungsfuehrenden Gehaeusen messtechnisch nachgewiesen?"}, DefaultSeverity: 4, DefaultExposure: 2, }, { @@ -338,6 +368,7 @@ func GetRobotCellPatterns() []HazardPattern { HarmDE: "Elektrischer Schlag bei Beruehren des Maschinengehaeuses oder leitfaehiger Oberflaechen.", AffectedDE: "Bedienpersonal, Wartungspersonal", ZoneDE: "Beruehrbare leitfaehige Oberflaechen der Anlage", + ClarificationQuestionsDE: []string{"Wurde der Schutzleiterwiderstand an allen leitfaehigen Oberflaechen gemessen und protokolliert?", "Liegen die Ableitstroeme unter 10 mA, oder ist einer der Massnahmen aus EN 60204-1 Ziff. 8.2.6 umgesetzt?"}, DefaultSeverity: 4, DefaultExposure: 2, }, { diff --git a/ai-compliance-sdk/internal/iace/hazard_patterns_robot_cell_ext.go b/ai-compliance-sdk/internal/iace/hazard_patterns_robot_cell_ext.go index f3b8e587..ad2b6427 100644 --- a/ai-compliance-sdk/internal/iace/hazard_patterns_robot_cell_ext.go +++ b/ai-compliance-sdk/internal/iace/hazard_patterns_robot_cell_ext.go @@ -152,6 +152,7 @@ func GetRobotCellPatternsExt() []HazardPattern { HarmDE: "Quetschungen, Schnittverletzungen durch rotierende Werkzeuge, Scheren an Achsbewegungen.", AffectedDE: "Einrichter, Wartungspersonal", ZoneDE: "Bearbeitungsraum der Werkzeugmaschine, Achsen, Werkzeug, Spannvorrichtung", + ClarificationQuestionsDE: []string{"Ist die Werkzeugmaschine (z.B. Robodrill) als CE-konformes Subsystem integriert? Herstellererklaerung anfordern.", "Sind sicherer Automatik- und Einrichtbetrieb durch die CE-Erklaerung der WZM abgedeckt oder erforderlich separate Sicherheitsfunktionen?"}, DefaultSeverity: 3, DefaultExposure: 3, }, // ================================================================ @@ -234,6 +235,7 @@ func GetRobotCellPatternsExt() []HazardPattern { HarmDE: "Elektrischer Schlag bei Beruehren des Maschinengehaeuses oder anderer leitfaehiger Teile.", AffectedDE: "Bedienpersonal, Wartungspersonal", ZoneDE: "Beruehrbare leitfaehige Oberflaechen der Anlage", + ClarificationQuestionsDE: []string{"Wurden alle Steckdosenkreise mit Fehlerstromschutzeinrichtung (RCD) ausgestattet und auf Wirksamkeit geprueft?", "Ist das Schutzleitersystem durchgaengig validiert und protokolliert?"}, DefaultSeverity: 4, DefaultExposure: 2, }, { diff --git a/ai-compliance-sdk/internal/iace/pattern_engine.go b/ai-compliance-sdk/internal/iace/pattern_engine.go index 3c8e4c1e..13032b9e 100644 --- a/ai-compliance-sdk/internal/iace/pattern_engine.go +++ b/ai-compliance-sdk/internal/iace/pattern_engine.go @@ -67,7 +67,8 @@ type PatternMatch struct { GeneratedHazardType string `json:"generated_hazard_type,omitempty"` MatchedFailureModes []string `json:"matched_failure_modes,omitempty"` ApplicableLifecycles []string `json:"applicable_lifecycles,omitempty"` - SuggestedMeasureIDs []string `json:"suggested_measure_ids,omitempty"` + SuggestedMeasureIDs []string `json:"suggested_measure_ids,omitempty"` + ClarificationQuestionsDE []string `json:"clarification_questions_de,omitempty"` } // HazardSuggestion is a suggested hazard from pattern matching. @@ -221,7 +222,8 @@ func (e *PatternEngine) Match(input MatchInput) *MatchOutput { GeneratedHazardType: p.GeneratedHazardType, MatchedFailureModes: matchedFMs, ApplicableLifecycles: p.ApplicableLifecycles, - SuggestedMeasureIDs: p.SuggestedMeasureIDs, + SuggestedMeasureIDs: p.SuggestedMeasureIDs, + ClarificationQuestionsDE: p.ClarificationQuestionsDE, }) for _, cat := range p.GeneratedHazardCats {