feat(iace): clarification questions + HP1632 Bersten + HP1637 KSS-Aerosol fix

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) <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-05-16 22:23:56 +02:00
parent 41023f6343
commit 5ea68ebea4
5 changed files with 65 additions and 4 deletions
@@ -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),
@@ -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
@@ -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,
},
{
@@ -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,
},
{
@@ -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 {