Files
breakpilot-compliance/ai-compliance-sdk/internal/iace/risk_estimation_range_test.go
T
Benjamin Admin a7dc12f30f feat(iace): risk as confidence range + label in benchmark tab
Report the tool's risk number as a plausible range with a confidence
label instead of a false-precision point value (confidence-aware
tonality — the assessment is confirmed by the DSB / safety expert).

- risk_estimation.go: EstimateConfidence (hoch/mittel/niedrig from how the
  contact mode resolved), EstimateRiskRange (S±1 and aggregate L=F+W+P ±1,
  the empirically validated per-parameter accuracy), RiskLevelRange; share
  the riskBandLabel thresholds with EstimateRiskLevel.
- risk_benchmark.go: RiskComparisonPair gains eng_risk_point/low/high +
  level + level_range + confidence; RiskAgreement gains high_confidence_pct.
- RiskComparison.tsx: per-hazard range "low–high (level range)" + point,
  confidence chip, and an aggregate confidence line; types in useBenchmark.ts.
- Unit tests for the range/confidence helpers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 23:04:56 +02:00

59 lines
2.2 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
import "testing"
func TestEstimateRiskRange(t *testing.T) {
tests := []struct {
name string
s, f, w, p int
wantLow, wantP, wantH int
}{
// S=4, L=F+W+P=8 → point 32; low 3*clampL(7)=21; high 5*clampL(9)=45.
{"typical electrical", 4, 3, 2, 3, 21, 32, 45},
// Min likelihood: L=3; low clamps L to 3 (clampL(2)=3) and S to 1.
{"low end clamps", 2, 1, 1, 1, 3, 6, 12},
// Max: S=5, L=15 → point 75; high clamps S to 5 and L to 15.
{"high end clamps", 5, 5, 5, 5, 56, 75, 75},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
low, point, high := EstimateRiskRange(tc.s, tc.f, tc.w, tc.p)
if low != tc.wantLow || point != tc.wantP || high != tc.wantH {
t.Errorf("EstimateRiskRange(%d,%d,%d,%d) = (%d,%d,%d), want (%d,%d,%d)",
tc.s, tc.f, tc.w, tc.p, low, point, high, tc.wantLow, tc.wantP, tc.wantH)
}
if low > point || point > high {
t.Errorf("range not ordered: low=%d point=%d high=%d", low, point, high)
}
})
}
}
func TestEstimateConfidence(t *testing.T) {
cases := []struct {
cats []string
scenario string
want string
}{
{[]string{"mechanical_hazard"}, "Quetschen der Hand im Werkzeugraum", "hoch"}, // keyword "quetsch"
{[]string{"electrical_hazard"}, "Elektrischer Schlag am Gehaeuse", "hoch"}, // keyword "elektrisch"
{[]string{"mechanical_hazard"}, "Allgemeine Restgefahr an der Anlage", "mittel"}, // category fallback
{[]string{"made_up_category"}, "Unspezifische Situation", "niedrig"}, // nothing
}
for _, tc := range cases {
if got := EstimateConfidence(tc.cats, tc.scenario); got != tc.want {
t.Errorf("EstimateConfidence(%v, %q) = %q, want %q", tc.cats, tc.scenario, got, tc.want)
}
}
}
func TestRiskLevelRange(t *testing.T) {
// Same band low+high → single label; spanning bands → "lowhigh".
if lvl, rng := RiskLevelRange(9, 12, 16); lvl != "gering" || rng != "gering" {
t.Errorf("single-band: got (%q,%q), want (gering,gering)", lvl, rng)
}
if lvl, rng := RiskLevelRange(21, 32, 45); lvl != "hoch" || rng != "mittelkritisch" {
t.Errorf("multi-band: got (%q,%q), want (hoch, mittelkritisch)", lvl, rng)
}
}