# Obligation Aggregation — Validated Shadow Results (2026-06-24)

Status: **bewiesen im Shadow auf macmini**, NICHT deployt, NICHT live geschaltet.
Code auf Branch `feat/obligation-aggregation`; das LLM-Tiering der recipients/transfer-
Controls liegt als DB-Marker nur auf macmini.

Dieser Stand validiert die Ausführung des [Legal Obligation Layer v1](legal_obligation_layer_v1.md)
über vier ineinandergreifende Schichten.

## Die vier Schichten

1. **Obligation Aggregation** — `compliance/services/obligation_aggregation.py`.
   Aggregiert Kriterium-/Control-Bewertungen zu Findings auf OBLIGATION-Ebene
   (Regulation → Obligation → Control → Criterion). Redundanz kollabiert per OR pro
   `legal_basis`-Anforderung; fail-safe Status (MET/PARTIAL/FAILED/NA/UNDETERMINED/OPEN).
2. **Applicability** — `compliance/services/obligation_applicability.py`.
   Prädikate (`has_third_country_transfer`, `uses_legitimate_interest`, `direct_marketing`,
   `legitimate_interest_or_public_task`) entscheiden bedingte Obligations → True/False/None
   (unbekannt → anwendbar, nie stille NA).
3. **Recall-limited Segregation** — `compliance/services/obligation_taxonomy.py` +
   `specialist_agents/dse/_obligation_shadow.py`.
   `decision_method_required=LLM` trennt FAILED ehrlich in `failed_by_current_checker`
   (echte Lücke) vs `recall_limited` (Prüfer kann mit aktueller Methode nicht verifizieren).
4. **Targeted LLM Fix** — recipients/transfer-Controls mit `tiered_criteria`
   (decision_method=LLM) → Layer 3 nutzt den **Haiku-Sufficiency-Judge** statt Keyword/Embedding.

## Shadow-Zahlen (7 Firmen, Live-Engine, Keyword/Embedding)

| | Wert |
|---|---|
| legacy control-findings | 136 |
| obligation findings | 29 |
| **Kollaps** | **4,7×** |
| davon echte Lücken | 23 |
| davon recall_limited | 6 (nur 2/7 Firmen, nur Drittland/Garantien) |
| MET (FP-Korrektur) | 46 |
| N/A (Applicability) | 2 |

`recall_limited` ist klein + konzentriert: ausschließlich `third_country_transfer_disclosed` /
`safeguards_disclosed` / `safeguards_accessible`, je 2/7 Firmen. `recipients_disclosed`
manifestierte nie als recall_limited (Keyword/Embedding trägt dort).

## Targeted LLM Fix — Validierung (teamviewer + safetykon)

Recall-Defekt-Diagnose (teamviewer): die Drittland-/Garantien-Offenlegung steht dicht in
einem Absatz („…außerhalb EU/EWR … Standardvertragsklauseln/Schutzmaßnahmen"), aber
**0/22 Controls** trafen — Keyword (Vokabular-Mismatch) und Embedding (cos 0.49–0.57, teils
falscher Chunk) versagen. Kein Schwellen-Fix → CONTENT/LLM-Klasse.

Nach LLM-Tiering (Haiku-Judge):

| | vorher (kw+emb) | nachher (LLM) |
|---|---|---|
| teamviewer findings | 5 | **0** |
| teamviewer recall_limited | 3 | **0** |
| safetykon findings | 7 | **4** |
| safetykon recall_limited | 3 | **0** |

- **teamviewer → 0 Findings:** DSE auf diesen Pflichten real konform; die 5 alten Findings
  waren Falsch-Positive des Keyword/Embedding-Prüfers.
- **safetykon → 4 (keine Über-Korrektur):** Drittland/Garantien → MET, aber
  `art20_right_exists_core` + `art20_machine_readable_format` bleiben **FAILED** (echte
  Portability-Lücke), `legitimate_interest_disclosed` → **NA** (Applicability).

## Eingesetztes Modell

Der Tiered-/Sufficiency-Pfad ist **fest auf Claude Haiku 4.5 verdrahtet**
(`checkers/router.py:build_spec` setzt für CONTENT/LLM `extra.judge="haiku"` →
`llm_checker._haiku` → `_call_anthropic`; validierter Judge P0.89/R0.91, Entscheidung
2026-06-22). **Nicht** die OVH-Kaskade (35b/120b), **nicht** Opus. Konsequenz: der Fix
reproduziert sich überall identisch, braucht aber einen gültigen Anthropic-Key für den
Haiku-Judge — auch auf dev.

## Nächster operativer Block (gegated, NICHT ausgeführt)

```
Deploy-Fenster frei (andere Session fertig)
  ↓
dev-DB-Tiering replizieren (die 22 recipients/transfer-Controls)
  ↓
Haiku-Judge auf dev bestätigen (gültiger Anthropic-Key — NICHT der OVH-Pfad)
  ↓
Shadow aktiv lassen (Telemetrie), Produktverhalten unverändert
  ↓
erst dann Umschalten planen
```

Folge-Cleanup: sobald LLM-Tiering Standard ist, wird die `recall_limited`-Segregation für
diese 4 Obligations obsolet (dann ist FAILED = echte Lücke, nicht Reichweitenproblem).
