feat(platform): live-wire AGB v2 + DSE v3 + Architektur-Tab (#29)
CI / detect-changes (push) Successful in 7s
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 / build-sha-integrity (push) Successful in 9s
CI / validate-canonical-controls (push) Successful in 12s
CI / loc-budget (push) Successful in 24s
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 3m11s
CI / test-go (push) Has been skipped
CI / iace-gt-coverage (push) Has been skipped
CI / test-python-backend (push) Successful in 24s
CI / test-python-document-crawler (push) Has been skipped
CI / test-python-dsms-gateway (push) Has been skipped

AGB v2 (decision_method routing, 71%FP->~0) + DSE v3 (4-layer, recovered from container) + Architektur-Tab into /sdk/agent live path. Incl CI robustness (detect-changes.sh + PR-head checkout) + security (hardcoded Qdrant key removed, gitleaks allowlist).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit was merged in pull request #29.
This commit is contained in:
2026-06-21 12:58:26 +00:00
parent 6b9c7984b4
commit 38a347a82a
44 changed files with 3861 additions and 104 deletions
@@ -0,0 +1,83 @@
"""Unit-Tests der Prüfer-Library. Embedding + LLM gemockt → kein Netzwerk."""
import asyncio
import compliance.services.llm_cascade as cascade_mod
import compliance.services.mc_embedding_matcher as emb_mod
from compliance.services.checkers.base import (
ControlSpec,
DecisionMethod,
DocContext,
VerificationMethod,
)
from compliance.services.checkers.embedding_checker import EmbeddingChecker
from compliance.services.checkers.llm_checker import LLMChecker
from compliance.services.checkers.reference_checker import ReferenceChecker
def _run(coro):
return asyncio.run(coro)
def test_reference_present_and_absent():
rc = ReferenceChecker()
spec = ControlSpec("data_protection", VerificationMethod.REFERENCE,
DecisionMethod.LINK_RESOLVER,
patterns=[r"datenschutz(erkl|bestimmung|hinweis)"])
r = _run(rc.check(spec, DocContext(
text="Details in unserer Datenschutzerklaerung: https://x.de/datenschutz")))
assert r.present is True
assert r.detail.get("link", "").startswith("https://")
r2 = _run(rc.check(spec, DocContext(text="Keine Angabe zum Datenschutz-Thema.")))
assert r2.present is False
def test_embedding_threshold(monkeypatch):
monkeypatch.setattr(emb_mod, "DIM", 3, raising=False)
monkeypatch.setattr(emb_mod, "_chunk_text", lambda t: [t], raising=False)
async def _embed(texts):
return [[1.0, 0.0, 0.0] for _ in texts]
monkeypatch.setattr(emb_mod, "_embed_texts", _embed, raising=False)
ec = EmbeddingChecker()
spec = ControlSpec("scope_t", VerificationMethod.CONTENT, DecisionMethod.EMBEDDING,
paraphrases=["Geltungsbereich"], embed_threshold=0.58)
monkeypatch.setattr(emb_mod, "_cosine", lambda a, b: 0.90, raising=False)
r = _run(ec.check(spec, DocContext(text="x" * 200)))
assert r.present is True and r.confidence >= 0.58
monkeypatch.setattr(emb_mod, "_cosine", lambda a, b: 0.20, raising=False)
r2 = _run(ec.check(spec, DocContext(text="x" * 200)))
assert r2.present is False
def test_embedding_offline_returns_none(monkeypatch):
async def _boom(texts):
raise ConnectionError("embedding-service down")
monkeypatch.setattr(emb_mod, "_embed_texts", _boom, raising=False)
ec = EmbeddingChecker()
spec = ControlSpec("scope_off", VerificationMethod.CONTENT, DecisionMethod.EMBEDDING,
paraphrases=["x"], embed_threshold=0.6)
r = _run(ec.check(spec, DocContext(text="y" * 200)))
assert r.present is None # fail-safe
def test_llm_present_and_absent(monkeypatch):
lc = LLMChecker()
spec = ControlSpec("delivery_timeframe", VerificationMethod.CONTENT, DecisionMethod.LLM,
topic_regex=r"liefer", question="Konkrete Lieferfrist?")
doc = DocContext(text=("1. Lieferung\nDie Ware wird innerhalb von 2 Werktagen "
"geliefert.\n") * 4)
async def _erfuellt(system, user, **kw):
return {"text": '{"verdict":"ERFUELLT","zitat":"2 Werktagen","begruendung":"x"}',
"source": "qwen", "confidence": 0.7}
monkeypatch.setattr(cascade_mod, "call_with_cascade", _erfuellt, raising=False)
assert _run(lc.check(spec, doc)).present is True
async def _fehlt(system, user, **kw):
return {"text": '{"verdict":"FEHLT"}', "source": "qwen"}
monkeypatch.setattr(cascade_mod, "call_with_cascade", _fehlt, raising=False)
assert _run(lc.check(spec, doc)).present is False