feat(iace): Sprint 3B — Human Interaction Model
- 6 Standard-Rollen: operator, maintenance_tech, programmer, cleaning_staff, bystander, supervisor - HumanRoles []string Feld in HazardPattern, MatchInput, PatternMatch - patternMatches() filtert Patterns nach Rolle (nil = feuert fuer alle Rollen) - MatchReason um human_role Typ erweitert (Explainability) - 25 bestehende Patterns mit Rollen annotiert: - Cobot HP059/062/064 → operator/programmer - Maintenance HP700-714 → maintenance_tech/programmer - Operational HP070/073-078/080 → operator/maintenance_tech/programmer - Init + Parser Handler reichen Roles an MatchInput durch - 4 neue Tests: NilFiresAlways, MaintenanceTechFilter, ProgrammerTeachMode, RoleCount Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -14,6 +14,9 @@ type MatchInput struct {
|
||||
// StateTransitions are active state transitions (format: "from→to").
|
||||
// Used to detect transition-specific hazards like unexpected restart.
|
||||
StateTransitions []string `json:"state_transitions,omitempty"`
|
||||
// HumanRoles are the human roles interacting with the machine in this project.
|
||||
// Used to filter patterns that only apply to specific roles (e.g. programmer, maintenance_tech).
|
||||
HumanRoles []string `json:"human_roles,omitempty"`
|
||||
}
|
||||
|
||||
// MatchOutput contains the results of pattern matching.
|
||||
@@ -53,6 +56,7 @@ type PatternMatch struct {
|
||||
RequiresExpert bool `json:"requires_expert,omitempty"`
|
||||
OperationalStates []string `json:"operational_states,omitempty"`
|
||||
StateTransitions []string `json:"state_transitions,omitempty"`
|
||||
HumanRoles []string `json:"human_roles,omitempty"`
|
||||
}
|
||||
|
||||
// HazardSuggestion is a suggested hazard from pattern matching.
|
||||
@@ -195,6 +199,12 @@ func (e *PatternEngine) Match(input MatchInput) *MatchOutput {
|
||||
reasons = append(reasons, MatchReason{Type: "state_transition", Tag: t, Met: transSet[t]})
|
||||
}
|
||||
}
|
||||
if len(p.HumanRoles) > 0 {
|
||||
roleSet := toSet(input.HumanRoles)
|
||||
for _, r := range p.HumanRoles {
|
||||
reasons = append(reasons, MatchReason{Type: "human_role", Tag: r, Met: roleSet[r]})
|
||||
}
|
||||
}
|
||||
|
||||
matchedPatterns = append(matchedPatterns, PatternMatch{
|
||||
PatternID: p.ID,
|
||||
@@ -214,6 +224,7 @@ func (e *PatternEngine) Match(input MatchInput) *MatchOutput {
|
||||
RequiresExpert: p.RequiresExpertCalculation,
|
||||
OperationalStates: p.OperationalStates,
|
||||
StateTransitions: p.StateTransitions,
|
||||
HumanRoles: p.HumanRoles,
|
||||
})
|
||||
|
||||
for _, cat := range p.GeneratedHazardCats {
|
||||
@@ -351,6 +362,21 @@ func patternMatches(p HazardPattern, tagSet map[string]bool, input MatchInput) b
|
||||
}
|
||||
}
|
||||
|
||||
// If pattern requires specific human roles, at least one must match.
|
||||
if len(p.HumanRoles) > 0 && len(input.HumanRoles) > 0 {
|
||||
found := false
|
||||
roleSet := toSet(input.HumanRoles)
|
||||
for _, r := range p.HumanRoles {
|
||||
if roleSet[r] {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user