feat(iace): Sprint 3A — Operational State Graph + fix(ucca) flaky keyword sort

State Graph:
- 9 Standard-Betriebszustaende (startup, homing, automatic_operation, manual_operation, teach_mode, maintenance, cleaning, emergency_stop, recovery_mode)
- 20 State-Transitions als gerichteter Graph
- OperationalStates + StateTransitions Felder in HazardPattern, MatchInput, PatternMatch
- patternMatches() filtert Patterns nach Betriebszustand (nil = feuert immer)
- Narrative-Parser extrahiert States aus Maschinenbeschreibung (22 Keywords + 4 Transition-Keywords)
- 27 bestehende Patterns mit State-Einschraenkungen annotiert (10 operational, 15 maintenance, 2 cobot)
- MatchReason um operational_state + state_transition Typen erweitert (Explainability)
- 6 neue Tests: NilFiresAlways, MaintenanceFilter, StateTransition, MatchReasons, Count, TransitionValid

UCCA fix:
- Stabiler Tiebreaker (Pattern-ID aufsteigend) bei gleichem Keyword-Score in MatchByKeywords
- Behebt flaky TestControlPatternIndex_MatchByKeywords (1/10 Failure-Rate durch Go map iteration order)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-05-10 08:05:02 +02:00
parent 33f0a64ff6
commit 77a497d930
10 changed files with 449 additions and 48 deletions
@@ -5,70 +5,70 @@ package iace
func GetMaintenanceExtPatterns() []HazardPattern {
return []HazardPattern{
// — Wartung allgemein (HP700-HP709) —
{ID: "HP700", NameDE: "LOTO-Fehler: Maschine nicht freigeschaltet", NameEN: "LOTO failure: not locked out",
{ID: "HP700", OperationalStates: []string{"maintenance"}, NameDE: "LOTO-Fehler: Maschine nicht freigeschaltet", NameEN: "LOTO failure: not locked out",
RequiredComponentTags: []string{"moving_part"}, RequiredLifecycles: []string{"maintenance"},
GeneratedHazardCats: []string{"mechanical_hazard", "safety_function_failure"},
SuggestedMeasureIDs: []string{"M054", "M082"}, SuggestedEvidenceIDs: []string{"E08", "E20"}, Priority: 95,
ScenarioDE: "Arbeit ohne Freischaltung der Maschine", TriggerDE: "Fehlende LOTO-Prozedur",
HarmDE: "Erfassen durch anlaufende Teile, Tod", AffectedDE: "Instandhalter", ZoneDE: "Gesamte Maschine",
DefaultSeverity: 5, DefaultExposure: 3},
{ID: "HP701", NameDE: "Restenergie trotz Abschaltung", NameEN: "Residual energy after shutdown",
{ID: "HP701", OperationalStates: []string{"maintenance"}, NameDE: "Restenergie trotz Abschaltung", NameEN: "Residual energy after shutdown",
RequiredComponentTags: []string{"moving_part"}, RequiredLifecycles: []string{"maintenance"},
GeneratedHazardCats: []string{"mechanical_hazard", "pneumatic_hydraulic"},
SuggestedMeasureIDs: []string{"M054", "M082"}, SuggestedEvidenceIDs: []string{"E08"}, Priority: 90,
ScenarioDE: "Gespeicherte Energie entlaedt sich bei Wartung", TriggerDE: "Nicht abgelassener Druckspeicher",
HarmDE: "Unkontrollierte Bewegung, Quetschung", AffectedDE: "Instandhalter", ZoneDE: "Antriebe, Speicher",
DefaultSeverity: 5, DefaultExposure: 3},
{ID: "HP702", NameDE: "Falsches Werkzeug bei Wartung", NameEN: "Wrong tool during maintenance",
{ID: "HP702", OperationalStates: []string{"maintenance"}, NameDE: "Falsches Werkzeug bei Wartung", NameEN: "Wrong tool during maintenance",
RequiredComponentTags: []string{"structural_part"}, RequiredLifecycles: []string{"maintenance"},
GeneratedHazardCats: []string{"mechanical_hazard"},
SuggestedMeasureIDs: []string{"M082"}, SuggestedEvidenceIDs: []string{"E20"}, Priority: 50,
ScenarioDE: "Ungeeignetes oder defektes Werkzeug", TriggerDE: "Falscher Schraubenschluessel",
HarmDE: "Abrutschen, Quetschung", AffectedDE: "Instandhalter", ZoneDE: "Wartungszugang",
DefaultSeverity: 3, DefaultExposure: 4},
{ID: "HP703", NameDE: "Fehlende Qualifikation des Instandhalters", NameEN: "Insufficient maintainer qualification",
{ID: "HP703", OperationalStates: []string{"maintenance"}, NameDE: "Fehlende Qualifikation des Instandhalters", NameEN: "Insufficient maintainer qualification",
RequiredComponentTags: []string{"electrical_part"}, RequiredLifecycles: []string{"maintenance"},
GeneratedHazardCats: []string{"electrical_hazard", "safety_function_failure"},
SuggestedMeasureIDs: []string{"M082", "M141"}, SuggestedEvidenceIDs: []string{"E20"}, Priority: 70,
ScenarioDE: "Unqualifiziertes Personal an Elektrik", TriggerDE: "Keine Elektrofachkraft",
HarmDE: "Stromschlag, Fehlverdrahtung", AffectedDE: "Instandhalter", ZoneDE: "Schaltschrank",
DefaultSeverity: 4, DefaultExposure: 3},
{ID: "HP704", NameDE: "Herabfallen schwerer Teile bei Demontage", NameEN: "Heavy parts falling during disassembly",
{ID: "HP704", OperationalStates: []string{"maintenance"}, NameDE: "Herabfallen schwerer Teile bei Demontage", NameEN: "Heavy parts falling during disassembly",
RequiredComponentTags: []string{"structural_part"}, RequiredLifecycles: []string{"maintenance"},
GeneratedHazardCats: []string{"mechanical_hazard"},
SuggestedMeasureIDs: []string{"M082", "M141"}, SuggestedEvidenceIDs: []string{"E20"}, Priority: 75,
ScenarioDE: "Schwere Teile fallen bei Demontage herab", TriggerDE: "Fehlende Abstuetzung",
HarmDE: "Quetschung, Frakturen, Tod", AffectedDE: "Instandhalter", ZoneDE: "Wartungsbereich",
DefaultSeverity: 5, DefaultExposure: 3},
{ID: "HP705", NameDE: "Vergessenes Werkzeug in Maschine", NameEN: "Forgotten tool in machine",
{ID: "HP705", OperationalStates: []string{"maintenance"}, NameDE: "Vergessenes Werkzeug in Maschine", NameEN: "Forgotten tool in machine",
RequiredComponentTags: []string{"moving_part"}, RequiredLifecycles: []string{"maintenance"},
GeneratedHazardCats: []string{"mechanical_hazard"},
SuggestedMeasureIDs: []string{"M082"}, SuggestedEvidenceIDs: []string{"E20"}, Priority: 65,
ScenarioDE: "Zurueckgelassenes Werkzeug wird Geschoss", TriggerDE: "Keine Werkzeugkontrolle",
HarmDE: "Herausgeschleudertes Teil, Verletzungen", AffectedDE: "Bedienpersonal", ZoneDE: "Arbeitsraum",
DefaultSeverity: 4, DefaultExposure: 2},
{ID: "HP706", NameDE: "Schnittwunden an scharfkantigen Teilen", NameEN: "Cuts on sharp-edged parts",
{ID: "HP706", OperationalStates: []string{"maintenance"}, NameDE: "Schnittwunden an scharfkantigen Teilen", NameEN: "Cuts on sharp-edged parts",
RequiredComponentTags: []string{"structural_part"}, RequiredLifecycles: []string{"maintenance"},
GeneratedHazardCats: []string{"mechanical_hazard"},
SuggestedMeasureIDs: []string{"M005", "M082"}, SuggestedEvidenceIDs: []string{"E20"}, Priority: 45,
ScenarioDE: "Scharfe Kanten und Grate verletzen", TriggerDE: "Fehlende Schutzhandschuhe",
HarmDE: "Schnittwunden, Abschuerfungen", AffectedDE: "Instandhalter", ZoneDE: "Blechverkleidungen",
DefaultSeverity: 2, DefaultExposure: 4},
{ID: "HP707", NameDE: "Verbrennung an heissen Teilen bei Wartung", NameEN: "Burn on hot parts during maintenance",
{ID: "HP707", OperationalStates: []string{"maintenance"}, NameDE: "Verbrennung an heissen Teilen bei Wartung", NameEN: "Burn on hot parts during maintenance",
RequiredComponentTags: []string{"high_temperature"}, RequiredLifecycles: []string{"maintenance"},
GeneratedHazardCats: []string{"thermal_hazard"},
SuggestedMeasureIDs: []string{"M005", "M082"}, SuggestedEvidenceIDs: []string{"E10"}, Priority: 60,
ScenarioDE: "Maschine nicht abgekuehlt vor Wartung", TriggerDE: "Zu kurze Abkuehlzeit",
HarmDE: "Kontaktverbrennungen", AffectedDE: "Instandhalter", ZoneDE: "Heizplatten, Motorgehaeuse",
DefaultSeverity: 3, DefaultExposure: 4},
{ID: "HP708", NameDE: "Fehlende Wartungsfreigabe", NameEN: "Missing maintenance permit",
{ID: "HP708", OperationalStates: []string{"maintenance"}, NameDE: "Fehlende Wartungsfreigabe", NameEN: "Missing maintenance permit",
RequiredComponentTags: []string{"structural_part"}, RequiredLifecycles: []string{"maintenance"},
GeneratedHazardCats: []string{"safety_function_failure"},
SuggestedMeasureIDs: []string{"M082", "M141"}, SuggestedEvidenceIDs: []string{"E20"}, Priority: 70,
ScenarioDE: "Wartung ohne formale Freigabe", TriggerDE: "Fehlender Erlaubnisschein",
HarmDE: "Unerwarteter Maschinenbetrieb", AffectedDE: "Instandhalter", ZoneDE: "Gesamte Maschine",
DefaultSeverity: 5, DefaultExposure: 3},
{ID: "HP709", NameDE: "Biologische Gefaehrdung bei KSS-Wartung", NameEN: "Biological hazard MWF maintenance",
{ID: "HP709", OperationalStates: []string{"maintenance"}, NameDE: "Biologische Gefaehrdung bei KSS-Wartung", NameEN: "Biological hazard MWF maintenance",
RequiredComponentTags: []string{"chemical_risk"}, RequiredLifecycles: []string{"maintenance"},
GeneratedHazardCats: []string{"material_environmental"},
SuggestedMeasureIDs: []string{"M005", "M082"}, SuggestedEvidenceIDs: []string{"E20"}, Priority: 50,
@@ -76,35 +76,35 @@ func GetMaintenanceExtPatterns() []HazardPattern {
HarmDE: "Hautinfektionen, Atemwegsbeschwerden", AffectedDE: "Instandhalter", ZoneDE: "KSS-System",
DefaultSeverity: 2, DefaultExposure: 3},
// — Einrichten / Umruesten (HP710-HP719) —
{ID: "HP710", NameDE: "Falsche Parameter nach Umruestung", NameEN: "Wrong parameters after changeover",
{ID: "HP710", OperationalStates: []string{"teach_mode"}, NameDE: "Falsche Parameter nach Umruestung", NameEN: "Wrong parameters after changeover",
RequiredComponentTags: []string{"programmable"}, RequiredLifecycles: []string{"setup"},
GeneratedHazardCats: []string{"safety_function_failure"},
SuggestedMeasureIDs: []string{"M106", "M082"}, SuggestedEvidenceIDs: []string{"E08"}, Priority: 75,
ScenarioDE: "Falsche Maschinenparameter nach Produktwechsel", TriggerDE: "Falsche Rezeptnummer",
HarmDE: "Uebergeschwindigkeit, Werkzeugbruch", AffectedDE: "Einrichter", ZoneDE: "Bedienterminal",
DefaultSeverity: 4, DefaultExposure: 3},
{ID: "HP711", NameDE: "Quetschung bei Werkzeugwechsel", NameEN: "Crushing during tool change",
{ID: "HP711", OperationalStates: []string{"maintenance"}, NameDE: "Quetschung bei Werkzeugwechsel", NameEN: "Crushing during tool change",
RequiredComponentTags: []string{"moving_part", "high_force"}, RequiredLifecycles: []string{"setup"},
GeneratedHazardCats: []string{"mechanical_hazard"},
SuggestedMeasureIDs: []string{"M003", "M054"}, SuggestedEvidenceIDs: []string{"E08"}, Priority: 80,
ScenarioDE: "Schwere Werkzeuge manuell gewechselt", TriggerDE: "Kein Hebezeug, Finger eingeklemmt",
HarmDE: "Quetschung, Amputation", AffectedDE: "Einrichter", ZoneDE: "Werkzeugaufnahme",
DefaultSeverity: 4, DefaultExposure: 4},
{ID: "HP712", NameDE: "Unkontrollierte Bewegung bei Testlauf", NameEN: "Uncontrolled movement test run",
{ID: "HP712", OperationalStates: []string{"teach_mode", "manual_operation"}, NameDE: "Unkontrollierte Bewegung bei Testlauf", NameEN: "Uncontrolled movement test run",
RequiredComponentTags: []string{"moving_part", "programmable"}, RequiredLifecycles: []string{"setup"},
GeneratedHazardCats: []string{"mechanical_hazard"},
SuggestedMeasureIDs: []string{"M106", "M054"}, SuggestedEvidenceIDs: []string{"E08"}, Priority: 80,
ScenarioDE: "Testlauf mit Person im Gefahrenbereich", TriggerDE: "Volle Geschwindigkeit, kein Schutz",
HarmDE: "Erfassen, Quetschen", AffectedDE: "Einrichter", ZoneDE: "Arbeitsraum",
DefaultSeverity: 5, DefaultExposure: 3},
{ID: "HP713", NameDE: "Einrichtbetrieb ohne reduzierte Geschwindigkeit", NameEN: "Setup without reduced speed",
{ID: "HP713", OperationalStates: []string{"teach_mode"}, NameDE: "Einrichtbetrieb ohne reduzierte Geschwindigkeit", NameEN: "Setup without reduced speed",
RequiredComponentTags: []string{"moving_part", "programmable"}, RequiredLifecycles: []string{"setup"},
GeneratedHazardCats: []string{"mechanical_hazard", "safety_function_failure"},
SuggestedMeasureIDs: []string{"M106", "M082"}, SuggestedEvidenceIDs: []string{"E08"}, Priority: 85,
ScenarioDE: "Volle Geschwindigkeit im Einrichtmodus", TriggerDE: "Defekter Betriebsartschalter",
HarmDE: "Erfassen bei voller Geschwindigkeit", AffectedDE: "Einrichter", ZoneDE: "Werkzeugbereich",
DefaultSeverity: 5, DefaultExposure: 3},
{ID: "HP714", NameDE: "Werkstueck faellt bei Aufspannung", NameEN: "Workpiece falls during clamping",
{ID: "HP714", OperationalStates: []string{"teach_mode", "maintenance"}, NameDE: "Werkstueck faellt bei Aufspannung", NameEN: "Workpiece falls during clamping",
RequiredComponentTags: []string{"structural_part"}, RequiredLifecycles: []string{"setup"},
GeneratedHazardCats: []string{"mechanical_hazard"},
SuggestedMeasureIDs: []string{"M082"}, SuggestedEvidenceIDs: []string{"E20"}, Priority: 55,