fix(iace): Initialize pipeline reads operational_states from metadata
The Betriebszustand-UI saved states to metadata.operational_states but the initialize handler only read states from the parsed narrative text. Now merges both sources so the UI selection actually affects which patterns fire during initialization. Added integration E2E test that verifies: 2 states → fewer patterns, 9 states → more patterns. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -96,14 +96,18 @@ func (h *IACEHandler) InitializeProject(c *gin.Context) {
|
||||
energyIDs = append(energyIDs, e.SourceID)
|
||||
}
|
||||
|
||||
// Merge explicit operational_states from UI with parsed states from narrative
|
||||
operationalStates := mergeStringSlices(parseResult.OperationalStates, extractOperationalStatesFromMetadata(project.Metadata))
|
||||
stateTransitions := parseResult.StateTransitions
|
||||
|
||||
engine := iace.NewPatternEngine()
|
||||
matchOutput := engine.Match(iace.MatchInput{
|
||||
ComponentLibraryIDs: componentIDs,
|
||||
EnergySourceIDs: energyIDs,
|
||||
LifecyclePhases: parseResult.LifecyclePhases,
|
||||
CustomTags: parseResult.CustomTags,
|
||||
OperationalStates: parseResult.OperationalStates,
|
||||
StateTransitions: parseResult.StateTransitions,
|
||||
OperationalStates: operationalStates,
|
||||
StateTransitions: stateTransitions,
|
||||
HumanRoles: parseResult.Roles,
|
||||
})
|
||||
steps = append(steps, InitStep{
|
||||
@@ -386,6 +390,46 @@ func deriveComponentType(tags []string) iace.ComponentType {
|
||||
return iace.ComponentTypeMechanical
|
||||
}
|
||||
|
||||
// extractOperationalStatesFromMetadata reads the explicit operational_states
|
||||
// selection that the user set via the Betriebszustand-UI.
|
||||
func extractOperationalStatesFromMetadata(metadata json.RawMessage) []string {
|
||||
if metadata == nil {
|
||||
return nil
|
||||
}
|
||||
var meta map[string]json.RawMessage
|
||||
if err := json.Unmarshal(metadata, &meta); err != nil {
|
||||
return nil
|
||||
}
|
||||
raw, ok := meta["operational_states"]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
var states []string
|
||||
if err := json.Unmarshal(raw, &states); err != nil {
|
||||
return nil
|
||||
}
|
||||
return states
|
||||
}
|
||||
|
||||
// mergeStringSlices merges two string slices, deduplicating entries.
|
||||
func mergeStringSlices(a, b []string) []string {
|
||||
seen := make(map[string]bool, len(a)+len(b))
|
||||
var result []string
|
||||
for _, s := range a {
|
||||
if !seen[s] {
|
||||
seen[s] = true
|
||||
result = append(result, s)
|
||||
}
|
||||
}
|
||||
for _, s := range b {
|
||||
if !seen[s] {
|
||||
seen[s] = true
|
||||
result = append(result, s)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// findHazardForMeasureByCategory finds a matching hazard for a measure.
|
||||
func findHazardForMeasureByCategory(measureCat string, hazardsByCategory map[string]uuid.UUID) uuid.UUID {
|
||||
// Direct match
|
||||
|
||||
Reference in New Issue
Block a user