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
@@ -102,6 +102,8 @@ func (h *IACEHandler) InitializeProject(c *gin.Context) {
EnergySourceIDs: energyIDs,
LifecyclePhases: parseResult.LifecyclePhases,
CustomTags: parseResult.CustomTags,
OperationalStates: parseResult.OperationalStates,
StateTransitions: parseResult.StateTransitions,
})
steps = append(steps, InitStep{
Name: "Patterns abgeglichen",
@@ -73,6 +73,8 @@ func (h *IACEHandler) ParseNarrative(c *gin.Context) {
EnergySourceIDs: energyIDs,
LifecyclePhases: parseResult.LifecyclePhases,
CustomTags: parseResult.CustomTags,
OperationalStates: parseResult.OperationalStates,
StateTransitions: parseResult.StateTransitions,
}
matchOutput := engine.Match(matchInput)