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

154 lines
6.1 KiB
Markdown
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.
# 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`:
```sql
-- 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
```python
# 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:
```python
# 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`