feat(iace): lifecycle phases in patterns + broader robot cell scenarios

- ApplicableLifecycles field in HazardPattern: patterns now declare which
  lifecycle phases the hazard applies to (Output, not just filter)
- Init handler writes first applicable lifecycle into Hazard.LifecyclePhase
- Robot cell patterns HP1600-1601 broadened: "Betrieb, Einrichten, Reinigung,
  Wartung, Fehlersuche" instead of only "Teach-Betrieb"
- All robot cell patterns get ApplicableLifecycles for proper phase display

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-05-14 22:38:02 +02:00
parent e4431da8d2
commit 4b9317b4fd
4 changed files with 28 additions and 12 deletions
@@ -204,6 +204,12 @@ func (h *IACEHandler) InitializeProject(c *gin.Context) {
}
}
// Join applicable lifecycles for the LifecyclePhase field
lifecycleStr := ""
if len(mp.ApplicableLifecycles) > 0 {
lifecycleStr = mp.ApplicableLifecycles[0]
}
hz, cerr := h.store.CreateHazard(ctx, iace.CreateHazardRequest{
ProjectID: projectID,
ComponentID: compID,
@@ -212,6 +218,7 @@ func (h *IACEHandler) InitializeProject(c *gin.Context) {
Category: cat,
Scenario: mp.ScenarioDE,
Function: iace.EncodeOpStates(mp.OperationalStates),
LifecyclePhase: lifecycleStr,
TriggerEvent: mp.TriggerDE,
PossibleHarm: mp.HarmDE,
AffectedPerson: mp.AffectedDE,
@@ -54,6 +54,10 @@ type HazardPattern struct {
// of the listed failure modes is relevant (by ComponentType match against project components).
// Empty/nil = fires regardless of failure modes (backwards compatible).
RequiredFailureModes []string `json:"required_failure_modes,omitempty"`
// ApplicableLifecycles lists the ISO 12100 lifecycle phases where this hazard
// is relevant. Written into the Hazard's LifecyclePhase field on creation.
// Empty = not set (pattern does not specify lifecycle applicability).
ApplicableLifecycles []string `json:"applicable_lifecycles,omitempty"`
}
// Standard human roles for machinery interaction (ISO 12100 + BetrSichV).
@@ -15,23 +15,25 @@ func GetRobotCellPatterns() []HazardPattern {
GeneratedHazardCats: []string{"mechanical_hazard"},
SuggestedMeasureIDs: []string{"M061", "M062", "M054"},
Priority: 95, MachineTypes: []string{"robotics_cobot", "automotive", "metalworking", "general_industry"},
ApplicableLifecycles: []string{"normal_operation", "setup", "teach_mode", "cleaning", "maintenance", "fault_clearing"},
ScenarioDE: "Person befindet sich im Bewegungsbereich des Roboterarms und wird zwischen Roboterarm und feststehenden Anlagenteilen eingeklemmt.",
TriggerDE: "Roboterarm bewegt sich waehrend Person im Gefahrenbereich steht (z.B. nach Betreten der Roboterzelle).",
TriggerDE: "Roboterarm bewegt sich waehrend Person im Gefahrenbereich steht (z.B. nach Betreten der Roboterzelle zur Reinigung, Wartung oder Stoerungsbeseitigung).",
HarmDE: "Quetschungen, Knochenbrueche, innere Verletzungen durch Einklemmen von Koerperteilen.",
AffectedDE: "Bedienpersonal, Einrichter, Wartungspersonal",
AffectedDE: "Bedienpersonal, Einrichter, Wartungspersonal, Reinigungspersonal",
ZoneDE: "Roboterarm, feststehende Anlagenteile innerhalb der Roboterzelle",
DefaultSeverity: 4, DefaultExposure: 3,
},
{
ID: "HP1601", NameDE: "Quetschen bei Teach-Betrieb am Roboter", NameEN: "Crushing during robot teach mode",
ID: "HP1601", NameDE: "Quetschen bei Einrichten/Teachen am Roboter", NameEN: "Crushing during robot setup/teach",
RequiredComponentTags: []string{"moving_part"},
GeneratedHazardCats: []string{"mechanical_hazard"},
SuggestedMeasureIDs: []string{"M054", "M061"},
Priority: 94, MachineTypes: []string{"robotics_cobot", "automotive", "metalworking", "general_industry"},
ScenarioDE: "Einrichter befindet sich zum Teachen/Programmieren in der Roboterzelle. Roboterarm bewegt sich unerwartet oder mit zu hoher Geschwindigkeit.",
TriggerDE: "Teach-Modus laesst Bewegung zu, Einrichter steht im Schwenkbereich des Arms.",
HarmDE: "Quetschungen, Prellungen durch Kontakt mit bewegtem Roboterarm.",
AffectedDE: "Einrichter, Programmierer",
ApplicableLifecycles: []string{"teach_mode", "setup", "changeover", "fault_clearing"},
ScenarioDE: "Person befindet sich zum Einrichten, Teachen oder zur Stoerungsbeseitigung in der Roboterzelle. Roboterarm bewegt sich unerwartet oder mit zu hoher Geschwindigkeit.",
TriggerDE: "Betriebsartenwahlschalter steht auf Einrichten, Roboter bewegt sich im Schwenkbereich.",
HarmDE: "Quetschungen, Prellungen durch Kontakt mit bewegtem Roboterarm oder Greifer.",
AffectedDE: "Einrichter, Programmierer, Wartungspersonal",
ZoneDE: "Roboterarm, Inneres der Roboterzelle",
DefaultSeverity: 3, DefaultExposure: 3,
},
@@ -40,7 +42,7 @@ func GetRobotCellPatterns() []HazardPattern {
RequiredComponentTags: []string{"moving_part", "guard"},
GeneratedHazardCats: []string{"mechanical_hazard"},
SuggestedMeasureIDs: []string{"M002", "M061"},
Priority: 93,
Priority: 93, ApplicableLifecycles: []string{"normal_operation", "setup", "cleaning", "maintenance", "fault_clearing"},
ScenarioDE: "Person greift ueber oder durch den Schutzzaun und erreicht den Bewegungsbereich des Roboterarms.",
TriggerDE: "Unzureichender Sicherheitsabstand zwischen Schutzzaun-Oberkante und Roboter-Schwenkbereich.",
HarmDE: "Quetschung von Hand oder Arm zwischen Roboterarm und feststehenden Teilen.",
@@ -53,7 +55,7 @@ func GetRobotCellPatterns() []HazardPattern {
RequiredComponentTags: []string{"moving_part", "guard"},
GeneratedHazardCats: []string{"mechanical_hazard"},
SuggestedMeasureIDs: []string{"M061", "M054", "M141"},
Priority: 94,
Priority: 94, ApplicableLifecycles: []string{"normal_operation", "setup", "cleaning", "maintenance", "fault_clearing", "changeover"},
ScenarioDE: "Person befindet sich in der Roboterzelle, Schutztuer wird geschlossen und Roboter startet. Person kann den Gefahrenbereich nicht rechtzeitig verlassen.",
TriggerDE: "Schutztuer schliesst waehrend Person im Innenraum. Wiederanlauf des Roboters ohne Quittierung.",
HarmDE: "Quetschungen, Stoss durch anlaufenden Roboter. Person kann sich nicht entziehen.",
@@ -66,7 +68,7 @@ func GetRobotCellPatterns() []HazardPattern {
RequiredComponentTags: []string{"moving_part", "guard"},
GeneratedHazardCats: []string{"mechanical_hazard"},
SuggestedMeasureIDs: []string{"M061", "M002"},
Priority: 92,
Priority: 92, ApplicableLifecycles: []string{"normal_operation", "setup", "cleaning", "changeover", "fault_clearing"},
ScenarioDE: "Roboterarm ueberschreitet den vorgesehenen Bewegungsbereich und trifft den Schutzzaun mit hoher Kraft.",
TriggerDE: "Fehler in der Bahnplanung oder Ausfall der Achsbegrenzung. Roboter faehrt ueber Software-Endschalter hinaus.",
HarmDE: "Teile des Schutzzauns werden herausgeschleudert, Person ausserhalb wird getroffen.",
@@ -83,6 +85,7 @@ func GetRobotCellPatterns() []HazardPattern {
GeneratedHazardCats: []string{"mechanical_hazard"},
SuggestedMeasureIDs: []string{"M054", "M061"},
Priority: 94, MachineTypes: []string{"robotics_cobot", "automotive", "metalworking", "general_industry"},
ApplicableLifecycles: []string{"normal_operation", "setup", "cleaning", "changeover"},
ScenarioDE: "Person greift in den Bereich des Greifers waehrend der Roboter ein Werkstueck aufnimmt oder ablegt. Hand wird zwischen Greifbacken und Werkstueck eingeklemmt.",
TriggerDE: "Greiferbacken schliessen waehrend Koerperteil im Greifbereich ist.",
HarmDE: "Quetschung oder Amputation von Fingern durch Greifkraft.",
@@ -124,7 +127,7 @@ func GetRobotCellPatterns() []HazardPattern {
RequiredComponentTags: []string{"entanglement_risk"},
GeneratedHazardCats: []string{"mechanical_hazard"},
SuggestedMeasureIDs: []string{"M002", "M061", "M003"},
Priority: 93,
Priority: 93, ApplicableLifecycles: []string{"normal_operation", "setup", "cleaning", "maintenance", "fault_clearing"},
ScenarioDE: "Person greift an Foerderband fuer Werkstueckzulauf oder -auslauf und wird zwischen beweglichen und feststehenden Teilen eingeklemmt.",
TriggerDE: "Hand oder Finger geraten zwischen Band und Umlenkrolle oder zwischen Werkstueck und Tunnelrahmen.",
HarmDE: "Quetschung von Fingern, Einzug von Kleidung oder Haaren.",
@@ -66,6 +66,7 @@ type PatternMatch struct {
HumanRoles []string `json:"human_roles,omitempty"`
GeneratedHazardType string `json:"generated_hazard_type,omitempty"`
MatchedFailureModes []string `json:"matched_failure_modes,omitempty"`
ApplicableLifecycles []string `json:"applicable_lifecycles,omitempty"`
}
// HazardSuggestion is a suggested hazard from pattern matching.
@@ -218,6 +219,7 @@ func (e *PatternEngine) Match(input MatchInput) *MatchOutput {
HumanRoles: p.HumanRoles,
GeneratedHazardType: p.GeneratedHazardType,
MatchedFailureModes: matchedFMs,
ApplicableLifecycles: p.ApplicableLifecycles,
})
for _, cat := range p.GeneratedHazardCats {