Files
breakpilot-compliance/ai-compliance-sdk/internal/iace/fmea_data_sources.go
T
Benjamin Admin cb82ff74c8 fix(iace): correct FMD-91/NPRD-91 licence — NOT public domain
Verified the actual PDF cover pages: FMD-91 (ADA259655) and NPRD-91
(ADA242083) carry "© 1991, IIT Research Institute. All Rights Reserved"
plus a DoD "distribution unlimited" statement. The distribution statement
permits obtaining/reading the document, NOT reproducing its tables in a
commercial product — treat like DIN/ISO. The earlier P1 docs wrongly
labelled them "public domain" (an unverified research claim).

- Correct the licence in fmea_data_sources.go note + mil_std_1629a_fmeca.md
  + fmd91_nprd_failure_modes.md (read-reference only; tables NOT reproduced).
- The bp_iace_fmea_kb collection was deleted from Qdrant (the mislabelled
  doc removed); methodology docs (MIL-STD/NASA, genuine PD) not re-ingested
  pending review. The Go methodology module (own scales, MIL-STD-anchored)
  is unaffected and stays.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-12 23:41:13 +02:00

101 lines
4.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package iace
// Open, public-domain methodology anchors for the auto-FMEA (P1 of the FMEA
// build plan). Every scale here is anchored on US-Government PUBLIC-DOMAIN
// sources — MIL-STD-882E (system-safety severity/probability) and MIL-STD-1629A
// (FMECA criticality). The 1-10 projection is BreakPilot's OWN scale; NO
// AIAG-VDA / SAE J1739 / IEC 60812 table is reproduced (those are copyrighted).
// Failure-rate (λ) and failure-mode-ratio (α) values come later from NPRD-91 /
// FMD-91 (RAC, public domain). See project_fmea_build_plan / opensource-fmea-sources.
// FMEADataSourcesNote is the audit/attribution line for the FMEA methodology.
const FMEADataSourcesNote = "FMEA-Methodik + Skalen verankert an US-Gov Public Domain " +
"(MIL-STD-1629A FMECA-Kritikalität, MIL-STD-882E Severity/Probability, NASA RCM, " +
"MIL-HDBK-217F). Das 1-10-Mapping ist BreakPilot-eigen. FMD-91/NPRD-91 (RAC) sind " +
"© IITRI „All Rights Reserved\" — nur Lese-Referenz, Tabellen werden NICHT reproduziert. " +
"KEINE AIAG-VDA/SAE/IEC-Tabelle reproduziert."
// FMEASeverityBand maps a MIL-STD-882E Table-I severity CATEGORY to our 1-10 S.
type FMEASeverityBand struct {
Category string `json:"category"` // "I".."IV"
LabelDE string `json:"label_de"`
Desc string `json:"desc"` // public-domain threshold (injury/$)
Severity int `json:"severity"` // our 1-10 projection
}
// MILStd882Severity returns the four MIL-STD-882E severity categories, ordered
// most→least severe, with our 1-10 projection. (882E is US-Gov public domain.)
func MILStd882Severity() []FMEASeverityBand {
return []FMEASeverityBand{
{Category: "I", LabelDE: "Katastrophal", Desc: "Tod, dauerhafte Vollinvalidität oder irreversibler schwerer Umweltschaden", Severity: 10},
{Category: "II", LabelDE: "Kritisch", Desc: "Dauerhafte Teilinvalidität oder Krankenhausaufenthalt mehrerer Personen", Severity: 7},
{Category: "III", LabelDE: "Marginal", Desc: "Verletzung/Erkrankung mit Ausfalltag(en)", Severity: 4},
{Category: "IV", LabelDE: "Vernachlässigbar", Desc: "Geringfügige Verletzung ohne Ausfalltag", Severity: 2},
}
}
// FMEAOccurrenceBand maps a MIL-STD-882E Table-II probability LEVEL to our 1-10
// O. LambdaMax is the upper bound (failures per operating hour) we use to bin a
// computed mode rate; the per-hour calibration is ours, anchored on 882E order.
type FMEAOccurrenceBand struct {
Level string `json:"level"` // "A".."F"
LabelDE string `json:"label_de"`
LambdaMax float64 `json:"lambda_max"` // inclusive upper bound, /h (0 ⇒ eliminated)
Occurrence int `json:"occurrence"` // our 1-10 projection
}
// MILStd882Probability returns the six MIL-STD-882E probability levels (individual
// item), ordered most→least frequent, with our 1-10 projection + a per-hour
// failure-rate band used by OccurrenceFromRate.
func MILStd882Probability() []FMEAOccurrenceBand {
return []FMEAOccurrenceBand{
{Level: "A", LabelDE: "Häufig", LambdaMax: 1, Occurrence: 10}, // ≥ 1e-1
{Level: "B", LabelDE: "Wahrscheinlich", LambdaMax: 1e-1, Occurrence: 8}, // 1e-2 .. 1e-1
{Level: "C", LabelDE: "Gelegentlich", LambdaMax: 1e-2, Occurrence: 6}, // 1e-3 .. 1e-2
{Level: "D", LabelDE: "Selten", LambdaMax: 1e-3, Occurrence: 4}, // 1e-6 .. 1e-3
{Level: "E", LabelDE: "Unwahrscheinlich", LambdaMax: 1e-6, Occurrence: 2},
{Level: "F", LabelDE: "Ausgeschlossen", LambdaMax: 0, Occurrence: 1},
}
}
// OccurrenceFromRate maps a mode failure rate (λp·α, failures per operating hour)
// onto the 1-10 occurrence axis via the MIL-STD-882E probability bands. A rate
// ≤ 0 is "eliminated" (1); anything ≥ 0.1/h saturates at "frequent" (10).
func OccurrenceFromRate(modeRatePerHour float64) int {
if modeRatePerHour <= 0 {
return 1
}
bands := MILStd882Probability()
// bands[0] (A) has the highest threshold; walk most→least frequent and take
// the first band whose lower edge the rate clears.
for i := 0; i < len(bands)-1; i++ {
lowerEdge := bands[i+1].LambdaMax // edge between band i and i+1
if modeRatePerHour > lowerEdge {
return bands[i].Occurrence
}
}
return bands[len(bands)-2].Occurrence // E (improbable) for tiny positive rates
}
// SeverityForCategory returns our 1-10 severity for a MIL-STD-882E category
// ("I".."IV"); 0 if unknown.
func SeverityForCategory(category string) int {
for _, b := range MILStd882Severity() {
if b.Category == category {
return b.Severity
}
}
return 0
}
// CriticalityCm computes the MIL-STD-1629A modal criticality
// Cm = λp · α · β · t, where λp = part failure rate (/h), α = failure-mode ratio
// (fraction of part failures in this mode), β = conditional probability the mode
// produces the analysed effect, t = operating hours. Fully public-domain method.
func CriticalityCm(lambdaP, alpha, beta, operatingHours float64) float64 {
if lambdaP < 0 || alpha < 0 || beta < 0 || operatingHours < 0 {
return 0
}
return lambdaP * alpha * beta * operatingHours
}