feat(iace): Erweiterungen 2-4 — FMEA Worksheet, Delta Modal, Textil+Agri
Build + Deploy / build-admin-compliance (push) Successful in 2m5s
Build + Deploy / build-backend-compliance (push) Successful in 3m2s
Build + Deploy / build-ai-sdk (push) Failing after 35s
Build + Deploy / build-developer-portal (push) Successful in 1m6s
Build + Deploy / build-tts (push) Successful in 1m31s
Build + Deploy / build-document-crawler (push) Successful in 41s
Build + Deploy / build-dsms-gateway (push) Successful in 27s
Build + Deploy / build-dsms-node (push) Successful in 17s
CI / branch-name (push) Has been skipped
Build + Deploy / trigger-orca (push) Has been skipped
CI / guardrail-integrity (push) Has been skipped
CI / loc-budget (push) Failing after 16s
CI / secret-scan (push) Has been skipped
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / nodejs-build (push) Successful in 2m25s
CI / dep-audit (push) Has been skipped
CI / sbom-scan (push) Has been skipped
CI / test-go (push) Successful in 40s
CI / test-python-backend (push) Successful in 36s
CI / test-python-document-crawler (push) Successful in 26s
CI / test-python-dsms-gateway (push) Successful in 21s
CI / validate-canonical-controls (push) Successful in 13s

Erweiterung 2: FMEA-Worksheet Tab (/fmea)
- Tabelle: Komponente | Typ | Fehlerart | Auswirkung | S | O | D | RPZ | Bewertung
- RPZ-Farbcodierung: >200 Kritisch, >100 Handlungsbedarf, >50 Beobachten
- Stats: Gesamt, Kritisch, Handlungsbedarf, Akzeptabel

Erweiterung 3: DeltaPreviewModal (wiederverwendbar)
- Modal zeigt +/- Patterns, Hazards, Massnahmen bei Aenderungen
- Nutzt POST /delta-analysis Endpoint
- Summary Grid + detaillierte Listen

Erweiterung 4: Textilmaschinen (EN ISO 11111) + Landmaschinen (ISO 4254)
- 21 neue Patterns: HP1550-HP1559 (Textil), HP1565-HP1575 (Agri)
- 23 neue Massnahmen: M452-M460 (Textil), M461-M474 (Agri)
- Walzenspalt, Zapfwelle, ROPS, autonomer Traktor, Siloexplosion etc.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-05-12 07:08:56 +02:00
parent 1866bb11ae
commit bcf78c120a
8 changed files with 759 additions and 0 deletions
@@ -0,0 +1,117 @@
'use client'
import { useState, useEffect } from 'react'
export interface FailureMode {
id: string
component_type: string
mode: string
name_de: string
name_en: string
effect: string
detection_hint: string
default_severity: number
default_occurrence: number
default_detection: number
}
export interface Component {
id: string
name: string
component_type: string
}
export interface FMEARow {
component: Component
failureMode: FailureMode
severity: number
occurrence: number
detection: number
rpz: number
}
export function useFMEA(projectId: string) {
const [rows, setRows] = useState<FMEARow[]>([])
const [loading, setLoading] = useState(true)
useEffect(() => {
loadData()
}, [projectId]) // eslint-disable-line react-hooks/exhaustive-deps
async function loadData() {
try {
// Load project components
const compRes = await fetch(`/api/sdk/v1/iace/projects/${projectId}/components`)
if (!compRes.ok) return
const compJson = await compRes.json()
const components: Component[] = (compJson.components || compJson || []).map(
(c: Record<string, unknown>) => ({
id: c.id as string,
name: c.name as string,
component_type: c.component_type as string || 'mechanical',
})
)
// Load failure modes for each component type (deduplicated)
const types = [...new Set(components.map((c) => c.component_type))]
const fmByType: Record<string, FailureMode[]> = {}
await Promise.all(
types.map(async (type) => {
const res = await fetch(`/api/sdk/v1/iace/failure-modes?component_type=${type}`)
if (res.ok) {
const json = await res.json()
fmByType[type] = json.failure_modes || []
}
})
)
// Also load general failure modes (no type filter)
const allRes = await fetch('/api/sdk/v1/iace/failure-modes')
let allFMs: FailureMode[] = []
if (allRes.ok) {
const json = await allRes.json()
allFMs = json.failure_modes || []
}
// Build FMEA rows: each component × its matching failure modes
const fmeaRows: FMEARow[] = []
for (const comp of components) {
const compFMs = fmByType[comp.component_type] || []
// Use type-specific FMs, or fallback to first 3 general FMs
const relevantFMs = compFMs.length > 0 ? compFMs : allFMs.slice(0, 3)
for (const fm of relevantFMs) {
const s = fm.default_severity || 5
const o = fm.default_occurrence || 5
const d = fm.default_detection || 5
fmeaRows.push({
component: comp,
failureMode: fm,
severity: s,
occurrence: o,
detection: d,
rpz: s * o * d,
})
}
}
// Sort by RPZ descending (highest risk first)
fmeaRows.sort((a, b) => b.rpz - a.rpz)
setRows(fmeaRows)
} catch (err) {
console.error('Failed to load FMEA data:', err)
} finally {
setLoading(false)
}
}
const stats = {
total: rows.length,
critical: rows.filter((r) => r.rpz > 200).length,
actionRequired: rows.filter((r) => r.rpz > 100 && r.rpz <= 200).length,
acceptable: rows.filter((r) => r.rpz <= 100).length,
}
return { rows, loading, stats }
}