Files
breakpilot-compliance/zeroclaw/INSTRUCTION-hardcoded-knowledge-migration.md
T
Benjamin Admin 891fc5bea0 docs: add keyword-based checker problem to migration instruction
mandatory_content_checker.py keywords break with alternative formulations.
Solution: LLM-based check per mandatory field (9 calls, parallelizable).
For other session to implement alongside Dict→Control migration.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-29 18:18:45 +02:00

6.1 KiB
Raw Blame History

Instruktion: Hartkodiertes Wissen → Control Library Migration

Branch: feat/zeroclaw-compliance-agent Repo: /Users/benjaminadmin/Projekte/breakpilot-compliance/ Erstellt: 2026-04-29 Review-Deadline: 2026-07-01

Problem

Der Compliance Agent hat 6 Dateien mit hartkodiertem Rechtswissen in Python-Dicts. Das Wissen veraltet und wird nicht von der Pipeline aktualisiert. Langfristig muss alles aus der Control Library kommen (166k+ Controls in compliance.canonical_controls).

Inventar (alle im Backend: backend-compliance/compliance/services/)

Datei Hartkodiert Zeilen Prioritaet
legal_basis_validator.py CORRECT_BASIS dict — 7 Lit-Zuordnungen (Art. 6 lit. a-f pro Zweck) ~50 LOC HOCH
service_registry.py SERVICE_REGISTRY dict — 82 Services mit Legal Refs ~500 LOC MITTEL
mandatory_content_checker.py MANDATORY_DSE_CONTENT (9 Felder) + MANDATORY_IMPRESSUM_CONTENT (5 Felder) ~80 LOC MITTEL
relevance_filter.py CONTROL_RELEVANCE dict — 7 Controls mit Keyword-Listen ~60 LOC MITTEL
consent-tester/services/script_analyzer.py SERVICE_PATTERNS — 19 Services (Duplikat von Registry) ~70 LOC NIEDRIG
consent-tester/services/banner_detector.py CMP_SELECTORS — 10 CMPs PERMANENT (technisch)

Migrationspfad pro Datei

Schritt 1: Controls in der Pipeline generieren

Fuer jedes Dict-Entry einen entsprechenden Control in der Pipeline generieren lassen.

Beispiel fuer legal_basis_validator.py:

-- Neuer Control in canonical_controls:
INSERT INTO compliance.canonical_controls (title, objective, requirements, scope_conditions, tags)
VALUES (
  'Cookie-Tracking erfordert Einwilligung (lit. a)',
  'Cookie-Tracking und Webanalyse duerfen nur mit ausdruecklicher Einwilligung (Art. 6 Abs. 1 lit. a DSGVO) erfolgen.',
  'Rechtsgrundlage fuer Cookie-Tracking muss Art. 6(1)(a) sein. Art. 6(1)(f) (berechtigtes Interesse) ist nach EuGH C-673/17 (Planet49) nicht zulaessig.',
  '{"applies_when": "cookie_tracking OR web_analytics"}',
  ARRAY['legal_basis', 'lit_mapping', 'cookie', 'planet49']
);

Benoetigte Controls (aus legal_basis_validator.py CORRECT_BASIS):

  1. cookie_tracking → lit. a (Planet49)
  2. web_analytics → lit. a (DSK Orientierungshilfe, §25 TDDDG)
  3. marketing_email → lit. a (Art. 7 DSGVO, §7 UWG)
  4. remarketing → lit. a (§25 TDDDG)
  5. credit_check → lit. b/f + Art. 22 Pflichthinweis
  6. social_media_embed → lit. a (Fashion ID Urteil)
  7. session_recording → lit. a (§25 TDDDG)

Benoetigte Controls (aus mandatory_content_checker.py):

  1. DSE muss Verantwortlichen nennen (Art. 13(1)(a))
  2. DSE muss DSB-Kontakt nennen (Art. 13(1)(b))
  3. DSE muss Zwecke nennen (Art. 13(1)(c))
  4. DSE muss Rechtsgrundlagen nennen (Art. 13(1)(c))
  5. DSE muss Speicherdauer nennen (Art. 13(2)(a))
  6. DSE muss Betroffenenrechte nennen (Art. 13(2)(b-d))
  7. DSE muss Beschwerderecht nennen (Art. 13(2)(d))
  8. DSE muss Drittlandtransfer nennen (Art. 13(1)(f))
  9. DSE muss automatisierte Entscheidungen nennen (Art. 13(2)(f))

Schritt 2: Agent-Code aendern — Control Library first, Dict as Fallback

# VORHER (hartkodiert):
CORRECT_BASIS = {"cookie_tracking": {"correct": "lit. a", ...}}

# NACHHER (Control Library first):
async def get_legal_basis_rule(purpose: str) -> dict | None:
    controls = await query_controls(tags=["lit_mapping", purpose])
    if controls:
        return controls[0]  # Control Library hat Vorrang
    logger.warning("No control found for %s — using hardcoded fallback", purpose)
    return CORRECT_BASIS.get(purpose)  # Fallback

Schritt 3: Dicts entfernen

Wenn alle Controls in der Library sind und der Agent sie zuverlaessig findet:

  • Dicts loeschen
  • Warning-Logs entfernen
  • Tests aktualisieren

Welche Datei NICHT migriert wird

banner_detector.py — die CMP-Selektoren sind technische CSS-Patterns, kein Rechtswissen. Die bleiben hartkodiert und werden aktualisiert wenn CMPs ihre UI aendern.

Erkennungszeichen im Code

Alle betroffenen Dateien haben:

  • ⚠️ TECHNISCHE SCHULD im Docstring
  • Review-Datum: 2026-07-01 im Header
  • logger.warning("... HARDCODED rules ...") bei Nutzung

Zusaetzliches Problem: Keyword-basierte Pflichtinhalte-Pruefung

Problem (identifiziert beim IHK Konstanz Test, 2026-04-29)

Der mandatory_content_checker.py prueft ob DSE-Pflichtangaben vorhanden sind per Keyword-Matching: "zweck" in text.lower(). Das bricht wenn:

  • Andere Formulierung: "Verarbeitungszwecke" statt "Zwecke"
  • Andere Sprache: Englische DSE auf deutscher Website
  • Umschreibung: "Wozu wir Ihre Daten nutzen" statt "Zwecke"

Gleiches Problem bei ECOMMERCE_INDICATORS in der gleichen Datei — hartkodierte Shop-Erkennung die neue Shop-Systeme nicht kennt.

Betroffene Stellen

Datei Dict/Liste Zeilen
mandatory_content_checker.py MANDATORY_DSE_CONTENT keywords (9 Felder) ~60 LOC
mandatory_content_checker.py MANDATORY_IMPRESSUM_CONTENT keywords (5 Felder) ~30 LOC
mandatory_content_checker.py ECOMMERCE_INDICATORS ~10 LOC

Loesung: LLM-basierte Pflichtinhalte-Pruefung

Statt hartkodierter Keywords → Qwen fragen:

# VORHER (hartkodiert, bricht bei neuer Formulierung):
found = any(kw in text_lower for kw in ["zweck", "purpose", "verarbeitungszweck"])

# NACHHER (LLM-basiert, sprachunabhaengig):
prompt = f"""
Pruefe ob der folgende Text Angaben zu den Zwecken der Datenverarbeitung
enthaelt (Art. 13 Abs. 1 lit. c DSGVO).
Antworte NUR mit: JA (mit kurzem Zitat) oder NEIN.
Text: {dse_text[:2000]}
"""
result = await query_qwen(prompt)
found = result.startswith("JA")

Aufwand

  • 9 Pflichtfelder × 1 LLM-Call = 9 Calls (parallelisierbar)
  • ~100 LOC Umbau
  • Fallback auf Keywords wenn LLM nicht verfuegbar

Prioritaet

MITTEL — die erweiterten Keywords funktionieren fuer 90% der Faelle. LLM-Pruefung ist robuster aber langsamer (~30s statt <1s).

Memory-Datei

Details: /Users/benjaminadmin/.claude/projects/-Users-benjaminadmin-Projekte-breakpilot-lehrer/memory/hardcoded_knowledge_debt.md