fix(impressum): Pattern fasst Geschäftsführung/Vorstand/Inhaber
CI / build-sha-integrity (push) Failing after 4s
CI / validate-canonical-controls (push) Successful in 11s
CI / loc-budget (push) Successful in 13s
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 2m21s
CI / test-go (push) Has been skipped
CI / iace-gt-coverage (push) Has been skipped
CI / test-python-backend (push) Successful in 29s
CI / detect-changes (push) Successful in 8s
CI / branch-name (push) Has been skipped
CI / guardrail-integrity (push) Has been skipped
CI / secret-scan (push) Has been skipped
CI / dep-audit (push) Has been skipped
CI / sbom-scan (push) Has been skipped
CI / test-python-document-crawler (push) Has been skipped
CI / test-python-dsms-gateway (push) Has been skipped
CI / build-sha-integrity (push) Failing after 4s
CI / validate-canonical-controls (push) Successful in 11s
CI / loc-budget (push) Successful in 13s
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 2m21s
CI / test-go (push) Has been skipped
CI / iace-gt-coverage (push) Has been skipped
CI / test-python-backend (push) Successful in 29s
CI / detect-changes (push) Successful in 8s
CI / branch-name (push) Has been skipped
CI / guardrail-integrity (push) Has been skipped
CI / secret-scan (push) Has been skipped
CI / dep-audit (push) Has been skipped
CI / sbom-scan (push) Has been skipped
CI / test-python-document-crawler (push) Has been skipped
CI / test-python-dsms-gateway (push) Has been skipped
Safetykon-Bug: 'Geschäftsführung:' (Sammelbegriff für GF einer GmbH)
matched das alte Pattern 'Geschäftsführer' nicht — False-Positive
IMPRESSUM-AGENT-VERTRETUNGSBERECHTIGTE_LABEL_KORREKT.
Pattern erweitert: Geschäftsführer|Geschäftsführung|Geschäftsführerin
+ Vorstand|Vorstandsvorsitzender + Inhaber|persönlich haftend.
Test test_safetykon_geschaeftsfuehrung_passes ergänzt (11/11 grün).
frontend: SlotCard zeigt jetzt Badge bei 0/0/0-Slots
('Dokument konnte nicht geladen werden') statt silent-fail, +
bei 0 Findings ein 'alle MCs OK'-Badge.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -288,6 +288,10 @@ function SlotCard({ slot, output, runId }: {
|
|||||||
}) {
|
}) {
|
||||||
const [showAll, setShowAll] = useState(false)
|
const [showAll, setShowAll] = useState(false)
|
||||||
const visibleFindings = showAll ? output.findings : output.findings.slice(0, 8)
|
const visibleFindings = showAll ? output.findings : output.findings.slice(0, 8)
|
||||||
|
const wasSkipped = output.mc_total > 0 &&
|
||||||
|
output.mc_ok === 0 && output.mc_na === 0 &&
|
||||||
|
output.mc_high === 0 && output.mc_medium === 0 && output.mc_low === 0
|
||||||
|
const allGreen = !wasSkipped && output.findings.length === 0
|
||||||
return (
|
return (
|
||||||
<div className="rounded-lg border bg-white p-4 space-y-3">
|
<div className="rounded-lg border bg-white p-4 space-y-3">
|
||||||
<div className="flex items-baseline gap-3">
|
<div className="flex items-baseline gap-3">
|
||||||
@@ -295,6 +299,16 @@ function SlotCard({ slot, output, runId }: {
|
|||||||
<span className="text-xs text-gray-500">
|
<span className="text-xs text-gray-500">
|
||||||
{output.duration_ms} ms · confidence {(output.confidence * 100).toFixed(0)}%
|
{output.duration_ms} ms · confidence {(output.confidence * 100).toFixed(0)}%
|
||||||
</span>
|
</span>
|
||||||
|
{wasSkipped && (
|
||||||
|
<span className="text-xs bg-amber-100 text-amber-800 px-2 py-0.5 rounded">
|
||||||
|
Dokument konnte nicht geladen werden (leer/zu kurz)
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{allGreen && (
|
||||||
|
<span className="text-xs bg-emerald-100 text-emerald-800 px-2 py-0.5 rounded">
|
||||||
|
Keine Findings — alle anwendbaren MCs OK
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
<a className="text-xs text-blue-600 hover:underline ml-auto"
|
<a className="text-xs text-blue-600 hover:underline ml-auto"
|
||||||
href={`/api/sdk/v1/specialist-agent/run/${runId}/artifacts`}
|
href={`/api/sdk/v1/specialist-agent/run/${runId}/artifacts`}
|
||||||
target="_blank" rel="noreferrer">
|
target="_blank" rel="noreferrer">
|
||||||
|
|||||||
@@ -103,8 +103,11 @@ MCS: tuple[MC, ...] = (
|
|||||||
severity_if_missing="HIGH",
|
severity_if_missing="HIGH",
|
||||||
patterns=(
|
patterns=(
|
||||||
re.compile(
|
re.compile(
|
||||||
r"(?:Gesch(?:ae|ä)ftsf(?:ue|ü)hrer|"
|
r"(?:Gesch(?:ae|ä)ftsf(?:ue|ü)hr(?:er|ung|erin)|"
|
||||||
r"Vertretungsberechtigt|vertreten\s+durch)"
|
r"Vorstand(?:svorsitzend(?:er|e))?|"
|
||||||
|
r"Vertretungsberechtigt|vertreten\s+durch|"
|
||||||
|
r"Inhaber(?:in)?|"
|
||||||
|
r"Pers(?:ö|oe)nlich\s+haftend)"
|
||||||
r"\s*[:.\s]",
|
r"\s*[:.\s]",
|
||||||
re.IGNORECASE,
|
re.IGNORECASE,
|
||||||
),
|
),
|
||||||
@@ -121,9 +124,11 @@ MCS: tuple[MC, ...] = (
|
|||||||
norm="§ 5 Abs. 1 Nr. 1 TMG (Deutsch-Pflicht, gerichtsfest)",
|
norm="§ 5 Abs. 1 Nr. 1 TMG (Deutsch-Pflicht, gerichtsfest)",
|
||||||
severity_if_missing="MEDIUM",
|
severity_if_missing="MEDIUM",
|
||||||
patterns=(re.compile(
|
patterns=(re.compile(
|
||||||
r"(?:Gesch(?:ae|ä)ftsf(?:ue|ü)hrer|"
|
r"(?:Gesch(?:ae|ä)ftsf(?:ue|ü)hr(?:er|ung|erin)|"
|
||||||
r"Vorstand|"
|
r"Vorstand(?:svorsitzend(?:er|e))?|"
|
||||||
r"Vertretungsberechtigt|vertreten\s+durch)"
|
r"Vertretungsberechtigt|vertreten\s+durch|"
|
||||||
|
r"Inhaber(?:in)?|"
|
||||||
|
r"Pers(?:ö|oe)nlich\s+haftend)"
|
||||||
r"\s*[:.\s]",
|
r"\s*[:.\s]",
|
||||||
re.IGNORECASE,
|
re.IGNORECASE,
|
||||||
),),
|
),),
|
||||||
|
|||||||
@@ -78,6 +78,28 @@ def test_tesla_missing_german_label(monkeypatch):
|
|||||||
assert "ust_id" in field_ids
|
assert "ust_id" in field_ids
|
||||||
|
|
||||||
|
|
||||||
|
def test_safetykon_geschaeftsfuehrung_passes(monkeypatch):
|
||||||
|
"""Geschäftsführung (statt -führer) muss als deutsches Label akzeptiert
|
||||||
|
werden — sonst False-Positive bei SafetyKon GmbH und ähnlichen."""
|
||||||
|
async def _no_cascade(*a, **kw): return None, []
|
||||||
|
monkeypatch.setattr(
|
||||||
|
"compliance.services.specialist_agents.impressum.agent.cascade",
|
||||||
|
_no_cascade,
|
||||||
|
)
|
||||||
|
txt = (
|
||||||
|
"SafetyKon GmbH\nMerzhauser Str. 144\n79100 Freiburg\n"
|
||||||
|
"Telefon: 0761/48 98 09 01\nE-Mail: info@safetykon.de\n"
|
||||||
|
"Geschäftsführung: Dr. Oliver Kirchwehm\n"
|
||||||
|
"Handelsregister AG Freiburg HRB 709859\n"
|
||||||
|
"USt-Id: DE288952921\n"
|
||||||
|
)
|
||||||
|
agent = ImpressumAgent()
|
||||||
|
out = _run(agent.evaluate(AgentInput(doc_type="impressum", text=txt)))
|
||||||
|
field_ids = {f.field_id for f in out.findings}
|
||||||
|
assert "vertretungsberechtigte" not in field_ids
|
||||||
|
assert "vertretungsberechtigte_label_korrekt" not in field_ids
|
||||||
|
|
||||||
|
|
||||||
def test_full_impressum_has_no_basic_findings(monkeypatch):
|
def test_full_impressum_has_no_basic_findings(monkeypatch):
|
||||||
async def _no_cascade(*a, **kw):
|
async def _no_cascade(*a, **kw):
|
||||||
return None, []
|
return None, []
|
||||||
|
|||||||
Reference in New Issue
Block a user