Files
breakpilot-compliance/ai-compliance-sdk/internal/iace/narrative_parser_roller_test.go
T
Benjamin Admin afb3f83f30 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>
2026-06-10 17:15:55 +02:00

38 lines
1.2 KiB
Go

package iace
import "testing"
// Regression: "Bodenroller" (a floor dolly the load sits on) and "Controller"
// must NOT be detected as a rotating mill roller (C009 "Walze"). Before the fix,
// the bare English keyword "roller" matched as a substring inside these German
// compounds and created a bogus Walze component for a crate-lift.
func TestParseNarrative_BodenrollerControllerNotWalze(t *testing.T) {
cases := []string{
"Das Kistenhubgeraet hebt Behaelter auf Bodenrollern und Transportwagen.",
"Beladung wahlweise von Bodenroller 400x600 mm.",
"Der SPS-Controller steuert den Hubantrieb.",
}
for _, text := range cases {
res := ParseNarrative(text)
for _, c := range res.Components {
if c.LibraryID == "C009" {
t.Errorf("text %q wrongly mapped to C009 (Walze) via %q", text, c.MatchedOn)
}
}
}
}
// The precise German term must still create the roller component.
func TestParseNarrative_WalzeDetectsC009(t *testing.T) {
res := ParseNarrative("Die Maschine besitzt eine angetriebene Walze zum Kalandrieren.")
found := false
for _, c := range res.Components {
if c.LibraryID == "C009" {
found = true
}
}
if !found {
t.Fatal("expected 'Walze' to detect component C009")
}
}