feat(iace): cross-domain precision overhaul + component review + schema reconcile

Engine precision (stop foreign-machine patterns leaking into a project):
- Wire project.MachineType into the engine machine-type gate (empty input no
  longer fires every machine class — press/cnc/excavator/crane/medical...).
- Capability-domain gating extended by 7 domains (outdoor, ventilation,
  machining, bulk, palletizer, playground, fitness) so domain-specific hazards
  only fire when the narrative names that domain; emitted via keyword_dictionary.
- Relevance backstop moved into iace (single gating contract, testable), and its
  dominant false-anchor class removed (a long pattern word no longer matches a
  short common token; prepositions/leitung added to the generic stoplist).
- New guard tests: TestCrossDomainPrecision (full pipeline, 0 foreign per GT) and
  TestPatternReachability now asserts 0 dead patterns. Both GTs keep coverage 1.0.

Reachability fix: the 51 dead patterns required electrical/pneumatic/hydraulic
tags nothing produced — renamed to the canonical electrical_energy/
pneumatic_pressure/hydraulic_pressure/hydraulic_part.

Component review (negation is best-effort + expert-correctable):
- Parser surfaces negated components (ComponentMatch.Negated) instead of dropping
  them; negated contribute no tags/energy → no phantom hazards.
- presence_status (vorhanden|nicht_vorhanden|geloescht) + ce_marked on components;
  only `vorhanden` feed matching. CE+safety-relevant flags the PL/SIL obligation.
- Force re-seed preserves the expert's component decisions instead of wiping them.
- Tag-based component→hazard assignment (was: all on the first component).
- Negation-aware narrative parsing ("keine Pneumatik" no longer extracts it).

Local-dev DB: ai-sdk sets search_path=compliance,core,public; reconcile migrations
152-156 bring the consolidated local iace tables to the current schema + add the
presence_status/ce_marked columns. Machine-type vocabulary endpoint for the form.

[migration-approved]

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-06-10 17:15:55 +02:00
parent 3bd4e0aaaf
commit afb3f83f30
47 changed files with 1275 additions and 169 deletions
@@ -11,7 +11,7 @@ func GetSpecificMachinePatterns() []HazardPattern {
{
ID: "HP730", NameDE: "Bersten eines Druckbehaelters", NameEN: "Pressure vessel burst",
RequiredComponentTags: []string{"high_pressure", "structural_part"},
RequiredEnergyTags: []string{"pneumatic"},
RequiredEnergyTags: []string{"pneumatic_pressure"},
GeneratedHazardCats: []string{"mechanical_hazard", "pneumatic_hydraulic"},
SuggestedMeasureIDs: []string{"M003", "M141"},
SuggestedEvidenceIDs: []string{"E01", "E11", "E20"},
@@ -26,7 +26,7 @@ func GetSpecificMachinePatterns() []HazardPattern {
{
ID: "HP731", NameDE: "Dampfaustritt an Flanschverbindung", NameEN: "Steam leak at flange connection",
RequiredComponentTags: []string{"high_pressure", "high_temperature"},
RequiredEnergyTags: []string{"thermal", "pneumatic"},
RequiredEnergyTags: []string{"thermal", "pneumatic_pressure"},
GeneratedHazardCats: []string{"thermal_hazard", "pneumatic_hydraulic"},
SuggestedMeasureIDs: []string{"M005", "M141"},
SuggestedEvidenceIDs: []string{"E10", "E11", "E20"},
@@ -41,7 +41,7 @@ func GetSpecificMachinePatterns() []HazardPattern {
{
ID: "HP732", NameDE: "Sicherheitsventil klemmt unter Druck", NameEN: "Safety valve stuck under pressure",
RequiredComponentTags: []string{"high_pressure", "safety_device"},
RequiredEnergyTags: []string{"pneumatic"},
RequiredEnergyTags: []string{"pneumatic_pressure"},
GeneratedHazardCats: []string{"safety_function_failure", "pneumatic_hydraulic"},
SuggestedMeasureIDs: []string{"M104", "M141"},
SuggestedEvidenceIDs: []string{"E01", "E08", "E11"},
@@ -58,7 +58,7 @@ func GetSpecificMachinePatterns() []HazardPattern {
{
ID: "HP733", NameDE: "Wasserschlag in Rohrleitung", NameEN: "Water hammer in pipeline",
RequiredComponentTags: []string{"high_pressure", "structural_part"},
RequiredEnergyTags: []string{"pneumatic"},
RequiredEnergyTags: []string{"pneumatic_pressure"},
GeneratedHazardCats: []string{"mechanical_hazard", "pneumatic_hydraulic"},
SuggestedMeasureIDs: []string{"M003", "M141"},
SuggestedEvidenceIDs: []string{"E01", "E11"},
@@ -103,7 +103,7 @@ func GetSpecificMachinePatterns() []HazardPattern {
{
ID: "HP736", NameDE: "Druckstoss bei schnellem Ventilschluss", NameEN: "Pressure surge from rapid valve closure",
RequiredComponentTags: []string{"high_pressure"},
RequiredEnergyTags: []string{"pneumatic"},
RequiredEnergyTags: []string{"pneumatic_pressure"},
GeneratedHazardCats: []string{"pneumatic_hydraulic"},
SuggestedMeasureIDs: []string{"M003", "M141"},
SuggestedEvidenceIDs: []string{"E01", "E11"},
@@ -133,7 +133,7 @@ func GetSpecificMachinePatterns() []HazardPattern {
{
ID: "HP738", NameDE: "Bersten des Schauglases am Druckbehaelter", NameEN: "Sight glass burst on pressure vessel",
RequiredComponentTags: []string{"high_pressure"},
RequiredEnergyTags: []string{"pneumatic"},
RequiredEnergyTags: []string{"pneumatic_pressure"},
GeneratedHazardCats: []string{"mechanical_hazard", "pneumatic_hydraulic"},
SuggestedMeasureIDs: []string{"M003", "M005", "M141"},
SuggestedEvidenceIDs: []string{"E01", "E11", "E20"},
@@ -148,7 +148,7 @@ func GetSpecificMachinePatterns() []HazardPattern {
{
ID: "HP739", NameDE: "Dampfkessel Trockenlauf", NameEN: "Boiler dry firing",
RequiredComponentTags: []string{"high_pressure", "high_temperature"},
RequiredEnergyTags: []string{"thermal", "pneumatic"},
RequiredEnergyTags: []string{"thermal", "pneumatic_pressure"},
GeneratedHazardCats: []string{"thermal_hazard", "pneumatic_hydraulic"},
SuggestedMeasureIDs: []string{"M104", "M141"},
SuggestedEvidenceIDs: []string{"E01", "E08", "E11"},
@@ -199,7 +199,7 @@ func GetSpecificMachinePatterns() []HazardPattern {
{
ID: "HP742", NameDE: "Oeluebertritt in Druckluftsystem", NameEN: "Oil carry-over into compressed air system",
RequiredComponentTags: []string{"high_pressure"},
RequiredEnergyTags: []string{"pneumatic"},
RequiredEnergyTags: []string{"pneumatic_pressure"},
GeneratedHazardCats: []string{"material_environmental"},
SuggestedMeasureIDs: []string{"M141"},
SuggestedEvidenceIDs: []string{"E01", "E20"},
@@ -214,7 +214,7 @@ func GetSpecificMachinePatterns() []HazardPattern {
{
ID: "HP743", NameDE: "Druckluftschlauch reisst und peitscht", NameEN: "Compressed air hose rupture and whiplash",
RequiredComponentTags: []string{"high_pressure"},
RequiredEnergyTags: []string{"pneumatic"},
RequiredEnergyTags: []string{"pneumatic_pressure"},
GeneratedHazardCats: []string{"mechanical_hazard", "pneumatic_hydraulic"},
SuggestedMeasureIDs: []string{"M003", "M005", "M141"},
SuggestedEvidenceIDs: []string{"E01", "E11", "E20"},
@@ -229,7 +229,7 @@ func GetSpecificMachinePatterns() []HazardPattern {
{
ID: "HP744", NameDE: "Pulsation in Druckleitung", NameEN: "Pulsation in pressure line",
RequiredComponentTags: []string{"high_pressure", "structural_part"},
RequiredEnergyTags: []string{"pneumatic"},
RequiredEnergyTags: []string{"pneumatic_pressure"},
GeneratedHazardCats: []string{"pneumatic_hydraulic"},
SuggestedMeasureIDs: []string{"M141"},
SuggestedEvidenceIDs: []string{"E01", "E11"},
@@ -278,7 +278,7 @@ func GetSpecificMachinePatterns() []HazardPattern {
{
ID: "HP747", NameDE: "Brand in Gondel einer Windenergieanlage", NameEN: "Fire in wind turbine nacelle",
RequiredComponentTags: []string{"high_temperature", "electrical_part"},
RequiredEnergyTags: []string{"electrical", "thermal"},
RequiredEnergyTags: []string{"electrical_energy", "thermal"},
GeneratedHazardCats: []string{"thermal_hazard", "electrical_hazard"},
SuggestedMeasureIDs: []string{"M141"},
SuggestedEvidenceIDs: []string{"E01", "E10", "E20"},
@@ -308,7 +308,7 @@ func GetSpecificMachinePatterns() []HazardPattern {
{
ID: "HP749", NameDE: "Blitzschlag an Windturbine", NameEN: "Lightning strike on wind turbine",
RequiredComponentTags: []string{"structural_part", "electrical_part"},
RequiredEnergyTags: []string{"electrical"},
RequiredEnergyTags: []string{"electrical_energy"},
GeneratedHazardCats: []string{"electrical_hazard"},
SuggestedMeasureIDs: []string{"M082", "M141"},
SuggestedEvidenceIDs: []string{"E01", "E10", "E20"},
@@ -327,7 +327,7 @@ func GetSpecificMachinePatterns() []HazardPattern {
{
ID: "HP750", NameDE: "Lichtbogen an DC-Steckverbindung", NameEN: "Arc fault at DC connector",
RequiredComponentTags: []string{"electrical_part"},
RequiredEnergyTags: []string{"electrical"},
RequiredEnergyTags: []string{"electrical_energy"},
GeneratedHazardCats: []string{"electrical_hazard", "thermal_hazard"},
SuggestedMeasureIDs: []string{"M082", "M141"},
SuggestedEvidenceIDs: []string{"E01", "E10", "E20"},
@@ -357,7 +357,7 @@ func GetSpecificMachinePatterns() []HazardPattern {
{
ID: "HP752", NameDE: "Elektrischer Schlag DC-Seite (Spannung bei Abschaltung)", NameEN: "DC shock (voltage present even when isolated)",
RequiredComponentTags: []string{"electrical_part", "stored_energy"},
RequiredEnergyTags: []string{"electrical"},
RequiredEnergyTags: []string{"electrical_energy"},
GeneratedHazardCats: []string{"electrical_hazard"},
SuggestedMeasureIDs: []string{"M082", "M141"},
SuggestedEvidenceIDs: []string{"E01", "E10", "E20"},
@@ -376,7 +376,7 @@ func GetSpecificMachinePatterns() []HazardPattern {
{
ID: "HP753", NameDE: "Thermal Runaway bei Lithium-Batterie", NameEN: "Thermal runaway of lithium battery",
RequiredComponentTags: []string{"stored_energy", "high_temperature"},
RequiredEnergyTags: []string{"electrical", "thermal"},
RequiredEnergyTags: []string{"electrical_energy", "thermal"},
GeneratedHazardCats: []string{"thermal_hazard", "electrical_hazard"},
SuggestedMeasureIDs: []string{"M005", "M141"},
SuggestedEvidenceIDs: []string{"E01", "E10", "E20"},
@@ -406,7 +406,7 @@ func GetSpecificMachinePatterns() []HazardPattern {
{
ID: "HP755", NameDE: "Elektrischer Schlag an Hochvolt-Batteriespeicher", NameEN: "Electric shock from high-voltage battery storage",
RequiredComponentTags: []string{"stored_energy", "electrical_part"},
RequiredEnergyTags: []string{"electrical"},
RequiredEnergyTags: []string{"electrical_energy"},
GeneratedHazardCats: []string{"electrical_hazard"},
SuggestedMeasureIDs: []string{"M082", "M141"},
SuggestedEvidenceIDs: []string{"E01", "E10", "E20"},