Add CLAUDE.md, MkDocs docs, .claude/rules

- CLAUDE.md: Comprehensive documentation for Lehrer KI platform
- docs-src: Klausur, Voice, Agent-Core, KI-Pipeline docs
- mkdocs.yml: Lehrer-specific nav with blue theme
- docker-compose: Added docs service (port 8010, profile: docs)
- .claude/rules: testing, docs, open-source, abiturkorrektur, vocab-worksheet, multi-agent, experimental-dashboard

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Boenisch
2026-02-12 00:49:25 +01:00
parent 5a31f52310
commit e22019b2d5
29 changed files with 7288 additions and 25 deletions

View File

@@ -0,0 +1,614 @@
# Abiturkorrektur-System - Entwicklerdokumentation
**WICHTIG: Diese Datei wird bei jedem Compacting gelesen. Alle Implementierungsdetails hier dokumentieren!**
---
## 1. Projektziel
Entwicklung eines KI-gestützten Korrektur-Systems für Deutsch-Abiturklausuren:
- **Zielgruppe**: Lehrer in Niedersachsen (Pilot), später alle Bundesländer
- **Kernproblem**: Erstkorrektur dauert 6 Stunden pro Arbeit
- **Lösung**: KI schlägt Bewertungen vor, Lehrer bestätigt/korrigiert
---
## 2. Architektur-Übersicht
```
┌─────────────────────────────────────────────────────────────┐
│ Frontend (Next.js) │
│ /website/app/admin/klausur-korrektur/ │
│ - page.tsx (Klausur-Liste) │
│ - [klausurId]/page.tsx (Studenten-Liste) │
│ - [klausurId]/[studentId]/page.tsx (Korrektur-Workspace) │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ klausur-service (FastAPI) │
│ Port 8086 - /klausur-service/backend/main.py │
│ - Klausur CRUD (/api/v1/klausuren) │
│ - Student Work (/api/v1/students) │
│ - Annotations (/api/v1/annotations) [NEU] │
│ - Gutachten Generation │
│ - Fairness Analysis │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Infrastruktur │
│ - Qdrant (Vektor-DB für RAG) │
│ - MinIO (Datei-Storage) │
│ - PostgreSQL (Metadaten) │
│ - Embedding-Service (Port 8087) │
└─────────────────────────────────────────────────────────────┘
```
---
## 3. Bestehende Backend-Komponenten (NUTZEN!)
### 3.1 Klausur-Service API (main.py)
```python
# Bereits implementiert:
GET/POST /api/v1/klausuren # Klausur CRUD
GET /api/v1/klausuren/{id} # Klausur Details
POST /api/v1/klausuren/{id}/students # Student Work hochladen
GET /api/v1/klausuren/{id}/students # Studenten-Liste
PUT /api/v1/students/{id}/criteria # Kriterien bewerten
PUT /api/v1/students/{id}/gutachten # Gutachten speichern
POST /api/v1/students/{id}/gutachten/generate # Gutachten generieren (KI)
GET /api/v1/klausuren/{id}/fairness # Fairness-Analyse
GET /api/v1/grade-info # Notensystem-Info
```
### 3.2 Datenmodelle (main.py)
```python
@dataclass
class Klausur:
id: str
title: str
subject: str = "Deutsch"
year: int = 2025
semester: str = "Abitur"
modus: str = "abitur" # oder "vorabitur"
eh_id: Optional[str] = None # Erwartungshorizont-Referenz
@dataclass
class StudentKlausur:
id: str
klausur_id: str
anonym_id: str
file_path: str
ocr_text: str = ""
criteria_scores: Dict[str, int] = field(default_factory=dict)
gutachten: str = ""
status: str = "UPLOADED"
raw_points: int = 0
grade_points: int = 0
# Status-Workflow:
# UPLOADED → OCR_PROCESSING → OCR_COMPLETE → ANALYZING →
# FIRST_EXAMINER → SECOND_EXAMINER → COMPLETED
```
### 3.3 Notensystem (15-Punkte)
```python
GRADE_THRESHOLDS = {
15: 95, 14: 90, 13: 85, 12: 80, 11: 75,
10: 70, 9: 65, 8: 60, 7: 55, 6: 50,
5: 45, 4: 40, 3: 33, 2: 27, 1: 20, 0: 0
}
DEFAULT_CRITERIA = {
"rechtschreibung": {"name": "Rechtschreibung", "weight": 15},
"grammatik": {"name": "Grammatik", "weight": 15},
"inhalt": {"name": "Inhalt", "weight": 40},
"struktur": {"name": "Struktur", "weight": 15},
"stil": {"name": "Stil", "weight": 15}
}
```
---
## 4. NEU ZU IMPLEMENTIEREN
### Phase 1: Korrektur-Workspace MVP
#### 4.1 Frontend-Struktur
```
/website/app/admin/klausur-korrektur/
├── page.tsx # Klausur-Übersicht (Liste aller Klausuren)
├── types.ts # TypeScript Interfaces
├── [klausurId]/
│ ├── page.tsx # Studenten-Liste einer Klausur
│ └── [studentId]/
│ └── page.tsx # Korrektur-Workspace (2/3-1/3)
└── components/
├── KlausurCard.tsx # Klausur in Liste
├── StudentList.tsx # Studenten-Übersicht
├── DocumentViewer.tsx # PDF/Bild-Anzeige (links, 2/3)
├── AnnotationLayer.tsx # SVG-Overlay für Markierungen
├── AnnotationToolbar.tsx # Werkzeuge
├── CorrectionPanel.tsx # Bewertungs-Panel (rechts, 1/3)
├── CriteriaScoreCard.tsx # Einzelnes Kriterium
├── EHSuggestionPanel.tsx # EH-Vorschläge via RAG
├── GutachtenEditor.tsx # Gutachten bearbeiten
└── StudentNavigation.tsx # Prev/Next Navigation
```
#### 4.2 Annotations-Backend (NEU in main.py)
```python
# Neues Datenmodell:
@dataclass
class Annotation:
id: str
student_work_id: str
page: int
position: dict # {x, y, width, height} in % (0-100)
type: str # 'rechtschreibung' | 'grammatik' | 'inhalt' | 'struktur' | 'stil' | 'comment'
text: str # Kommentar-Text
severity: str # 'minor' | 'major' | 'critical'
suggestion: str # Korrekturvorschlag (bei RS/Gram)
created_by: str # User-ID (EK oder ZK)
created_at: datetime
role: str # 'first_examiner' | 'second_examiner'
linked_criterion: Optional[str] # Verknüpfung zu Kriterium
# Neue Endpoints:
POST /api/v1/students/{id}/annotations # Erstellen
GET /api/v1/students/{id}/annotations # Abrufen
PUT /api/v1/annotations/{id} # Ändern
DELETE /api/v1/annotations/{id} # Löschen
```
#### 4.3 UI-Layout Spezifikation
```
┌──────────────────────────────────────────────────────────────────────┐
│ Header: Klausur-Titel | Student: Anonym-123 | [← Prev] [5/24] [Next →]│
├─────────────────────────────────────────┬────────────────────────────┤
│ │ Tabs: [Kriterien] [Gutachten]│
│ ┌─────────────────────────────────┐ │ │
│ │ │ │ ▼ Rechtschreibung (15%) │
│ │ Dokument-Anzeige │ │ [====|====] 70/100 │
│ │ (PDF/Bild mit Zoom) │ │ 12 Fehler markiert │
│ │ │ │ │
│ │ + Annotation-Overlay │ │ ▼ Grammatik (15%) │
│ │ (SVG Layer) │ │ [====|====] 80/100 │
│ │ │ │ │
│ │ │ │ ▼ Inhalt (40%) │
│ │ │ │ [====|====] 65/100 │
│ │ │ │ EH-Vorschläge: [Laden] │
│ └─────────────────────────────────┘ │ │
│ │ ▼ Struktur (15%) │
│ Toolbar: [RS] [Gram] [Kommentar] │ [====|====] 75/100 │
│ [Zoom+] [Zoom-] [Fit] │ │
│ │ ▼ Stil (15%) │
│ Seiten: [1] [2] [3] [4] [5] │ [====|====] 70/100 │
│ │ │
│ │ ━━━━━━━━━━━━━━━━━━━━━━━━━━ │
│ │ Gesamtnote: 10 Punkte (2-) │
│ │ [Gutachten generieren] │
│ │ [Speichern] [Abschließen] │
├─────────────────────────────────────────┴────────────────────────────┤
│ 2/3 Breite │ 1/3 Breite │
└──────────────────────────────────────────────────────────────────────┘
```
---
## 5. Implementierungs-Reihenfolge
### Phase 1.1: Grundgerüst (AKTUELL)
1. ✅ Dokumentation erstellen
2. [ ] `/website/app/admin/klausur-korrektur/page.tsx` - Klausur-Liste
3. [ ] `/website/app/admin/klausur-korrektur/types.ts` - TypeScript Types
4. [ ] Navigation in AdminLayout.tsx hinzufügen
5. [ ] Deploy + Test
### Phase 1.2: Korrektur-Workspace
1. [ ] `[klausurId]/page.tsx` - Studenten-Liste
2. [ ] `[klausurId]/[studentId]/page.tsx` - Workspace
3. [ ] `components/DocumentViewer.tsx` - Bild/PDF Anzeige
4. [ ] `components/CorrectionPanel.tsx` - Bewertungs-Panel
5. [ ] Deploy + Test mit Lehrer
### Phase 1.3: Annotations-System
1. [ ] Backend: Annotations-Endpoints in main.py
2. [ ] `components/AnnotationLayer.tsx` - SVG Overlay
3. [ ] `components/AnnotationToolbar.tsx` - Werkzeuge
4. [ ] Farbkodierung: RS=rot, Gram=blau, Inhalt=grün
5. [ ] Deploy + Test
### Phase 1.4: EH-Integration
1. [ ] `components/EHSuggestionPanel.tsx`
2. [ ] Backend: `/api/v1/students/{id}/eh-suggestions`
3. [ ] RAG-Query mit Student-Text
4. [ ] Deploy + Test
### Phase 1.5: Gutachten-Editor
1. [ ] `components/GutachtenEditor.tsx`
2. [ ] Beleg-Verlinkung zu Annotations
3. [ ] Gutachten-Generierung Button
4. [ ] Deploy + Test
---
## 6. API-Konfiguration
```typescript
// Frontend API Base URLs
const KLAUSUR_SERVICE = process.env.NEXT_PUBLIC_KLAUSUR_SERVICE_URL || 'http://localhost:8086'
// Endpoints:
// Klausuren
GET ${KLAUSUR_SERVICE}/api/v1/klausuren
POST ${KLAUSUR_SERVICE}/api/v1/klausuren
GET ${KLAUSUR_SERVICE}/api/v1/klausuren/{id}
GET ${KLAUSUR_SERVICE}/api/v1/klausuren/{id}/students
// Studenten
GET ${KLAUSUR_SERVICE}/api/v1/students/{id}
GET ${KLAUSUR_SERVICE}/api/v1/students/{id}/file // Dokument-Download
PUT ${KLAUSUR_SERVICE}/api/v1/students/{id}/criteria
PUT ${KLAUSUR_SERVICE}/api/v1/students/{id}/gutachten
POST ${KLAUSUR_SERVICE}/api/v1/students/{id}/gutachten/generate
// Annotations (NEU)
GET ${KLAUSUR_SERVICE}/api/v1/students/{id}/annotations
POST ${KLAUSUR_SERVICE}/api/v1/students/{id}/annotations
PUT ${KLAUSUR_SERVICE}/api/v1/annotations/{id}
DELETE ${KLAUSUR_SERVICE}/api/v1/annotations/{id}
// System
GET ${KLAUSUR_SERVICE}/api/v1/grade-info
```
---
## 7. Deployment-Prozess
```bash
# 1. Dateien auf Mac Mini synchronisieren
rsync -avz --delete \
--exclude 'node_modules' --exclude '.next' --exclude '.git' \
/Users/benjaminadmin/Projekte/breakpilot-pwa/website/ \
macmini:/Users/benjaminadmin/Projekte/breakpilot-pwa/website/
# 2. Website-Container neu bauen
ssh macmini "/usr/local/bin/docker compose \
-f /Users/benjaminadmin/Projekte/breakpilot-pwa/docker-compose.yml \
build --no-cache website"
# 3. Container neu starten
ssh macmini "/usr/local/bin/docker compose \
-f /Users/benjaminadmin/Projekte/breakpilot-pwa/docker-compose.yml \
up -d website"
# 4. Testen unter:
# http://macmini:3000/admin/klausur-korrektur
```
---
## 8. Bundesland-Spezifika (Niedersachsen Pilot)
```json
// /klausur-service/backend/policies/bundeslaender.json
{
"NI": {
"name": "Niedersachsen",
"grading_mode": "points_15",
"requires_gutachten": true,
"zk_visibility": "full", // ZK sieht EK-Korrektur
"third_correction_threshold": 4, // Ab 4 Punkte Diff
"colors": {
"first_examiner": "#dc2626", // Rot
"second_examiner": "#16a34a" // Grün
},
"criteria_weights": {
"rechtschreibung": 15,
"grammatik": 15,
"inhalt": 40,
"struktur": 15,
"stil": 15
}
}
}
```
---
## 9. Wichtige Dateien (Referenz)
| Datei | Beschreibung |
|-------|--------------|
| `/klausur-service/backend/main.py` | Haupt-API, alle Endpoints |
| `/klausur-service/backend/eh_pipeline.py` | BYOEH Verarbeitung |
| `/klausur-service/backend/qdrant_service.py` | RAG Vector-Suche |
| `/klausur-service/backend/hybrid_search.py` | Hybrid Search |
| `/website/components/admin/AdminLayout.tsx` | Admin Navigation |
| `/website/app/admin/ocr-labeling/page.tsx` | Referenz für 2/3-1/3 Layout |
---
## 10. Testing-Checkliste
### Nach jeder Phase:
- [ ] Seite lädt ohne Fehler
- [ ] API-Calls funktionieren (DevTools Network)
- [ ] Responsives Layout korrekt
- [ ] Lehrer kann Workflow durchführen
### Lehrer-Test-Szenarien:
1. Klausur erstellen
2. 3+ Studentenarbeiten hochladen
3. Erste Arbeit korrigieren (alle Kriterien)
4. Annotations setzen
5. Gutachten generieren
6. Zur nächsten Arbeit navigieren
7. Fairness-Check nach allen Arbeiten
---
## 11. Phase 2: Zweitkorrektur-System (NEU)
### 11.1 Neue Backend-Endpoints (main.py)
```python
# Zweitkorrektur Workflow
POST /api/v1/students/{id}/start-zweitkorrektur # ZK starten (nach EK)
POST /api/v1/students/{id}/submit-zweitkorrektur # ZK-Ergebnis abgeben
# Einigung (bei Diff 3 Punkte)
POST /api/v1/students/{id}/einigung # Einigung einreichen
# Drittkorrektur (bei Diff >= 4 Punkte)
POST /api/v1/students/{id}/assign-drittkorrektor # DK zuweisen
POST /api/v1/students/{id}/submit-drittkorrektur # DK-Ergebnis (final)
# Workflow-Status & Visibility-Filtering
GET /api/v1/students/{id}/examiner-workflow # Workflow-Status abrufen
GET /api/v1/students/{id}/annotations-filtered # Policy-gefilterte Annotations
```
### 11.2 Workflow-Status
```python
class ExaminerWorkflowStatus(str, Enum):
NOT_STARTED = "not_started"
EK_IN_PROGRESS = "ek_in_progress"
EK_COMPLETED = "ek_completed"
ZK_ASSIGNED = "zk_assigned"
ZK_IN_PROGRESS = "zk_in_progress"
ZK_COMPLETED = "zk_completed"
EINIGUNG_REQUIRED = "einigung_required"
EINIGUNG_COMPLETED = "einigung_completed"
DRITTKORREKTUR_REQUIRED = "drittkorrektur_required"
DRITTKORREKTUR_ASSIGNED = "drittkorrektur_assigned"
DRITTKORREKTUR_IN_PROGRESS = "drittkorrektur_in_progress"
COMPLETED = "completed"
```
### 11.3 Visibility-Regeln (aus bundeslaender.json)
| Modus | ZK sieht EK-Annotations | ZK sieht EK-Note | ZK sieht EK-Gutachten |
|-------|-------------------------|------------------|----------------------|
| `blind` | Nein | Nein | Nein |
| `semi` (Bayern) | Ja | Nein | Nein |
| `full` (NI, Default) | Ja | Ja | Ja |
### 11.4 Konsens-Regeln
| Differenz EK-ZK | Aktion |
|-----------------|--------|
| 0-2 Punkte | Auto-Konsens (Durchschnitt) |
| 3 Punkte | Einigung erforderlich |
| >= 4 Punkte | Drittkorrektur erforderlich |
---
## 12. Aktueller Stand
**Datum**: 2026-01-21
**Phase**: Alle Phasen abgeschlossen
**Status**: MVP komplett - bereit fuer Produktionstest
### Abgeschlossen:
- [x] Phase 1: Korrektur-Workspace MVP
- [x] Phase 1.1: Grundgerüst (Klausur-Liste, Studenten-Liste)
- [x] Phase 1.2: Annotations-System
- [x] Phase 1.3: RS/Grammatik Overlays
- [x] Phase 1.4: EH-Vorschläge via RAG
- [x] Phase 2.1 Backend: Zweitkorrektur-Endpoints
- [x] Phase 2.2 Backend: Einigung-Endpoint
- [x] Phase 2.3 Backend: Drittkorrektur-Trigger
- [x] Phase 2.1 Frontend: ZK-Modus UI
- [x] Phase 2.2 Frontend: Einigung-Screen
- [x] Phase 3.1: Fairness-Dashboard Frontend
- [x] Phase 3.2: Ausreißer-Liste mit Quick-Adjust
- [x] Phase 3.3: Noten-Histogramm & Heatmap
- [x] Phase 4.1: PDF-Export Backend (reportlab)
- [x] Phase 4.2: PDF-Export Frontend
- [x] Phase 4.3: Vorabitur-Modus mit EH-Templates
### URLs:
- Klausur-Korrektur: `/admin/klausur-korrektur`
- Fairness-Dashboard: `/admin/klausur-korrektur/[klausurId]/fairness`
### PDF-Export Endpoints:
- `GET /api/v1/students/{id}/export/gutachten` - Einzelnes Gutachten als PDF
- `GET /api/v1/students/{id}/export/annotations` - Anmerkungen als PDF
- `GET /api/v1/klausuren/{id}/export/overview` - Notenübersicht als PDF
- `GET /api/v1/klausuren/{id}/export/all-gutachten` - Alle Gutachten als PDF
### Vorabitur-Modus Endpoints:
- `GET /api/v1/vorabitur/templates` - Liste aller EH-Templates
- `GET /api/v1/vorabitur/templates/{aufgabentyp}` - Template-Details
- `POST /api/v1/klausuren/{id}/vorabitur-eh` - Custom EH erstellen
- `GET /api/v1/klausuren/{id}/vorabitur-eh` - Verknuepften EH abrufen
- `PUT /api/v1/klausuren/{id}/vorabitur-eh` - EH aktualisieren
### Verfuegbare Aufgabentypen:
- `textanalyse_pragmatisch` - Sachtexte, Reden, Kommentare
- `gedichtanalyse` - Lyrik/Gedichte
- `prosaanalyse` - Romane, Kurzgeschichten
- `dramenanalyse` - Dramatische Texte
- `eroerterung_textgebunden` - Textgebundene Eroerterung
---
## 13. Lehrer-Anleitung (Schritt-fuer-Schritt)
### 13.1 Zugang zum System
**Weg 1: Ueber das Haupt-Dashboard**
1. Oeffnen Sie `http://macmini:8000/app` im Browser
2. Klicken Sie auf die Kachel "Abiturklausuren"
3. Sie werden automatisch zur Korrektur-Oberflaeche weitergeleitet
**Weg 2: Direkter Zugang**
1. Oeffnen Sie direkt `http://macmini:3000/admin/klausur-korrektur`
### 13.2 Zwei Einstiegs-Optionen
Beim ersten Besuch sehen Sie die Willkommens-Seite mit zwei Optionen:
#### Option A: Schnellstart (Direkt hochladen)
- Ideal wenn Sie sofort loslegen moechten
- Keine manuelle Klausur-Erstellung erforderlich
- System erstellt automatisch eine Klausur im Hintergrund
**Schritte:**
1. Klicken Sie auf "Schnellstart - Direkt hochladen"
2. **Schritt 1**: Ziehen Sie Ihre eingescannten Arbeiten (PDF/JPG/PNG) in den Upload-Bereich
3. **Schritt 2**: Optional - Waehlen Sie den Aufgabentyp und beschreiben Sie die Aufgabenstellung
4. **Schritt 3**: Pruefen Sie die Zusammenfassung und klicken "Korrektur starten"
5. Sie werden automatisch zur Korrektur-Ansicht weitergeleitet
#### Option B: Neue Klausur erstellen (Standard)
- Empfohlen fuer regelmaessige Nutzung
- Volle Metadaten (Fach, Jahr, Kurs, Modus)
- Unterstuetzt Zweitkorrektur-Workflow
**Schritte:**
1. Klicken Sie auf "Neue Klausur erstellen"
2. Geben Sie Titel, Fach, Jahr und Semester ein
3. Waehlen Sie den Modus:
- **Abitur**: Fuer offizielle Abitur-Pruefungen mit NiBiS-EH
- **Vorabitur**: Fuer Uebungsklausuren mit eigenem EH
4. Bei Vorabitur: Waehlen Sie Aufgabentyp und beschreiben Sie die Aufgabenstellung
5. Klicken Sie "Klausur erstellen"
### 13.3 Arbeiten hochladen
Nach Erstellung der Klausur:
1. Oeffnen Sie die Klausur aus der Liste
2. Klicken Sie "Arbeiten hochladen"
3. Waehlen Sie die eingescannten Dateien (PDF oder Bilder)
4. Geben Sie optional anonyme IDs (z.B. "Arbeit-1", "Arbeit-2")
5. Das System startet automatisch die OCR-Erkennung
### 13.4 Korrigieren
**Korrektur-Workspace (2/3-1/3 Layout):**
- Links (2/3): Das Originaldokument mit Zoom-Funktion
- Rechts (1/3): Bewertungspanel mit Kriterien
**Schritt fuer Schritt:**
1. Oeffnen Sie eine Arbeit durch Klick auf "Korrigieren"
2. Lesen Sie die Arbeit im linken Bereich (Zoom mit +/-)
3. Setzen Sie Anmerkungen durch Klick auf das Dokument
4. Waehlen Sie den Anmerkungstyp:
- **RS** (rot): Rechtschreibfehler
- **Gram** (blau): Grammatikfehler
- **Inhalt** (gruen): Inhaltliche Anmerkungen
- **Kommentar**: Allgemeine Bemerkungen
5. Bewerten Sie die 5 Kriterien im rechten Panel:
- Rechtschreibung (15%)
- Grammatik (15%)
- Inhalt (40%)
- Struktur (15%)
- Stil (15%)
6. Klicken Sie "EH-Vorschlaege laden" fuer KI-Unterstuetzung
7. Klicken Sie "Gutachten generieren" fuer einen KI-Vorschlag
8. Bearbeiten Sie das Gutachten nach Bedarf
9. Klicken Sie "Speichern" und dann "Naechste Arbeit"
### 13.5 Fairness-Analyse
Nach Korrektur mehrerer Arbeiten:
1. Klicken Sie auf "Fairness-Dashboard" in der Klausur-Ansicht
2. Pruefen Sie:
- **Noten-Histogramm**: Ist die Verteilung realistisch?
- **Ausreisser**: Gibt es ungewoehnlich hohe/niedrige Noten?
- **Kriterien-Heatmap**: Sind Kriterien konsistent bewertet?
3. Nutzen Sie "Quick-Adjust" um Anpassungen vorzunehmen
### 13.6 PDF-Export
1. In der Klausur-Ansicht klicken Sie "PDF-Export"
2. Waehlen Sie:
- **Einzelgutachten**: PDF fuer einen Schueler
- **Alle Gutachten**: Gesamtes PDF fuer alle Arbeiten
- **Notenuebersicht**: Uebersicht aller Noten
- **Anmerkungen**: Alle Annotationen als PDF
### 13.7 Zweitkorrektur (Optional)
Fuer offizielle Abitur-Klausuren:
1. Erstkorrektur abschliessen (Status: "Abgeschlossen")
2. Klicken Sie "Zweitkorrektur starten"
3. Der Zweitkorrektor bewertet unabhaengig
4. Bei Differenz >= 3 Punkte: Einigung erforderlich
5. Bei Differenz >= 4 Punkte: Drittkorrektur wird automatisch ausgeloest
### 13.8 Haeufige Fragen
**F: Kann ich eine Korrektur unterbrechen und spaeter fortsetzen?**
A: Ja, alle Aenderungen werden automatisch gespeichert.
**F: Was passiert mit meinen Daten?**
A: Alle Daten werden lokal auf dem Schulserver gespeichert. Keine Cloud-Speicherung.
**F: Kann ich den KI-Vorschlag komplett ueberschreiben?**
A: Ja, das Gutachten ist frei editierbar. Der KI-Vorschlag ist nur ein Startpunkt.
**F: Wie funktioniert die OCR-Erkennung?**
A: Das System erkennt Handschrift automatisch. Bei schlechter Lesbarkeit koennen Sie manuell nachbessern.
---
## 14. Integration Dashboard (Port 8000)
### 14.1 Aenderungen in dashboard.py
Die Funktion `openKlausurService()` wurde aktualisiert:
```javascript
// Alte Version: Oeffnete Port 8086 (Backend)
// Neue Version: Oeffnet Port 3000 (Next.js Frontend)
function openKlausurService() {
let baseUrl;
if (window.location.hostname === 'macmini') {
baseUrl = 'http://macmini:3000';
} else {
baseUrl = 'http://localhost:3000';
}
window.open(baseUrl + '/admin/klausur-korrektur', '_blank');
}
```
### 14.2 Neue Frontend-Features
- **Willkommens-Tab**: Erster Tab fuer neue Benutzer mit Workflow-Erklaerung
- **Direktupload-Wizard**: 3-Schritt-Wizard fuer Schnellstart
- **Drag & Drop**: Arbeiten per Drag & Drop hochladen
- **localStorage-Persistenz**: System merkt sich wiederkehrende Benutzer

View File

@@ -0,0 +1,91 @@
# Dokumentations-Regeln
## Automatische Dokumentations-Aktualisierung
**WICHTIG:** Bei JEDER Code-Änderung muss die entsprechende Dokumentation aktualisiert werden!
## Wann Dokumentation aktualisieren?
### API-Änderungen
Wenn du einen Endpoint änderst, hinzufügst oder entfernst:
- Aktualisiere `/docs/api/consent-service-api.md` (Go Endpoints)
- Aktualisiere `/docs/api/backend-api.md` (Python Endpoints)
### Neue Funktionen/Klassen
Wenn du neue Funktionen, Klassen oder Module erstellst:
- Aktualisiere `/docs/consent-service/README.md` (für Go)
- Aktualisiere `/docs/backend/README.md` (für Python)
### Architektur-Änderungen
Wenn du die Systemarchitektur änderst:
- Aktualisiere `/docs/architecture/system-architecture.md`
- Aktualisiere `/docs/architecture/data-model.md` (bei DB-Änderungen)
### Neue Konfigurationsoptionen
Wenn du neue Umgebungsvariablen oder Konfigurationen hinzufügst:
- Aktualisiere die entsprechende README
- Füge zur `guides/local-development.md` hinzu
## Dokumentations-Format
### API-Endpoints dokumentieren
```markdown
### METHOD /path/to/endpoint
Kurze Beschreibung.
**Request Body:**
\`\`\`json
{
"field": "value"
}
\`\`\`
**Response (200):**
\`\`\`json
{
"result": "value"
}
\`\`\`
**Errors:**
- `400`: Beschreibung
- `401`: Beschreibung
```
### Funktionen dokumentieren
```markdown
### FunctionName (file.go:123)
\`\`\`go
func FunctionName(param Type) ReturnType
\`\`\`
**Beschreibung:** Was macht die Funktion?
**Parameter:**
- `param`: Beschreibung
**Rückgabe:** Beschreibung
```
## Checkliste nach Code-Änderungen
Vor dem Abschluss einer Aufgabe prüfe:
- [ ] Wurden neue API-Endpoints hinzugefügt? → API-Docs aktualisieren
- [ ] Wurden Datenmodelle geändert? → data-model.md aktualisieren
- [ ] Wurden neue Konfigurationen hinzugefügt? → README aktualisieren
- [ ] Wurden neue Abhängigkeiten hinzugefügt? → requirements.txt/go.mod UND Docs
- [ ] Wurde die Architektur geändert? → architecture/ aktualisieren
## Beispiel: Vollständige Dokumentation einer neuen Funktion
Wenn du z.B. `GetUserStats()` im Go Service hinzufügst:
1. **Code schreiben** in `internal/services/stats_service.go`
2. **API-Doc aktualisieren** in `docs/api/consent-service-api.md`
3. **Service-Doc aktualisieren** in `docs/consent-service/README.md`
4. **Test schreiben** (siehe testing.md)

View File

@@ -0,0 +1,250 @@
# Experimental Dashboard - Apple Weather Style UI
**Status:** In Entwicklung
**Letzte Aktualisierung:** 2026-01-24
**URL:** http://macmini:3001/dashboard-experimental
---
## Uebersicht
Das Experimental Dashboard implementiert einen **Apple Weather App Style** mit:
- Ultra-transparenten Glassmorphism-Cards (~8% Opacity)
- Dunklem Sternenhimmel-Hintergrund mit Parallax
- Weisser Schrift auf monochromem Design
- Schwebenden Nachrichten (FloatingMessage) mit ~4% Background
- Nuetzlichen Widgets: Uhr, Wetter, Kompass, Diagramme
---
## Design-Prinzipien
| Prinzip | Umsetzung |
|---------|-----------|
| **Transparenz** | Cards mit 8% Opacity, Messages mit 4% |
| **Verschmelzung** | Elemente verschmelzen mit dem Hintergrund |
| **Monochrom** | Weisse Schrift, keine bunten Akzente |
| **Subtilitaet** | Dezente Hover-Effekte, sanfte Animationen |
| **Nuetzlichkeit** | Echte Informationen (Uhrzeit, Wetter) |
---
## Dateistruktur
```
/studio-v2/
├── app/
│ └── dashboard-experimental/
│ └── page.tsx # Haupt-Dashboard (740 Zeilen)
├── components/
│ └── spatial-ui/
│ ├── index.ts # Exports
│ ├── SpatialCard.tsx # Original SpatialCard (nicht verwendet)
│ └── FloatingMessage.tsx # Schwebende Nachrichten
└── lib/
└── spatial-ui/
├── index.ts # Exports
├── depth-system.ts # Design Tokens
├── PerformanceContext.tsx # Adaptive Qualitaet
└── FocusContext.tsx # Focus-Modus
```
---
## Komponenten
### GlassCard
Ultra-transparente Card fuer alle Inhalte.
```typescript
interface GlassCardProps {
children: React.ReactNode
className?: string
onClick?: () => void
size?: 'sm' | 'md' | 'lg' // Padding: 16px, 20px, 24px
delay?: number // Einblend-Verzoegerung in ms
}
```
**Styling:**
- Background: `rgba(255, 255, 255, 0.08)` (8%)
- Hover: `rgba(255, 255, 255, 0.12)` (12%)
- Border: `1px solid rgba(255, 255, 255, 0.1)`
- Blur: 24px (adaptiv)
- Border-Radius: 24px (rounded-3xl)
### AnalogClock
Analoge Uhr mit Sekundenzeiger.
- Stunden-Zeiger: Weiss, dick
- Minuten-Zeiger: Weiss/80%, duenn
- Sekunden-Zeiger: Orange (#fb923c)
- 12 Stundenmarkierungen
- Aktualisiert jede Sekunde
### Compass
Kompass im Apple Weather Style.
```typescript
interface CompassProps {
direction?: number // Grad (0 = Nord, 90 = Ost, etc.)
}
```
- Nord-Nadel: Rot (#ef4444)
- Sued-Nadel: Weiss
- Kardinalrichtungen: N (rot), S, W, O
### BarChart
Balkendiagramm fuer Wochen-Statistiken.
```typescript
interface BarChartProps {
data: { label: string; value: number; highlight?: boolean }[]
maxValue?: number
}
```
- Highlight-Balken mit Gradient (blau → lila)
- Normale Balken: 20% weiss
- Labels unten, Werte oben
### ProgressRing
Kreisfoermiger Fortschrittsanzeiger.
```typescript
interface ProgressRingProps {
progress: number // 0-100
size?: number // Default: 80px
strokeWidth?: number // Default: 6px
label: string
value: string
color?: string // Farbe des Fortschritts
}
```
### TemperatureDisplay
Wetter-Anzeige mit Icon und Temperatur.
```typescript
interface TemperatureDisplayProps {
temp: number
condition: 'sunny' | 'cloudy' | 'rainy' | 'snowy' | 'partly_cloudy'
}
```
### FloatingMessage
Schwebende Benachrichtigungen von rechts.
**Aktuell:**
- Background: 4% Opacity
- Blur: 24px
- Border: `1px solid rgba(255, 255, 255, 0.12)`
- Auto-Dismiss mit Progress-Bar
- 3 Antwort-Optionen: Antworten, Oeffnen, Spaeter
- Typewriter-Effekt fuer Text
---
## Farbpalette
| Element | Wert |
|---------|------|
| Background | `from-slate-900 via-indigo-950 to-slate-900` |
| Card Background | `rgba(255, 255, 255, 0.08)` |
| Card Hover | `rgba(255, 255, 255, 0.12)` |
| Message Background | `rgba(255, 255, 255, 0.04)` |
| Border | `rgba(255, 255, 255, 0.1)` |
| Text Primary | `text-white` |
| Text Secondary | `text-white/50` bis `text-white/40` |
| Accent Blue | `#60a5fa` |
| Accent Purple | `#a78bfa` |
| Accent Orange | `#fb923c` (Sekundenzeiger) |
| Accent Red | `#ef4444` (Kompass Nord) |
---
## Performance-System
Das Dashboard nutzt das **PerformanceContext** fuer adaptive Qualitaet:
| Quality Level | Blur | Parallax | Animationen |
|---------------|------|----------|-------------|
| high | 24px | Ja | Spring |
| medium | 17px | Ja | Standard |
| low | 0px | Nein | Reduziert |
| minimal | 0px | Nein | Keine |
**FPS-Monitor** unten links zeigt:
- Aktuelle FPS
- Quality Level
- Blur/Parallax Status
---
## Deployment
```bash
# 1. Sync zu Mac Mini
rsync -avz --delete \
--exclude 'node_modules' --exclude '.next' --exclude '.git' \
/Users/benjaminadmin/Projekte/breakpilot-pwa/studio-v2/ \
macmini:/Users/benjaminadmin/Projekte/breakpilot-pwa/studio-v2/
# 2. Build
ssh macmini "/usr/local/bin/docker compose \
-f /Users/benjaminadmin/Projekte/breakpilot-pwa/docker-compose.yml \
build --no-cache studio-v2"
# 3. Deploy
ssh macmini "/usr/local/bin/docker compose \
-f /Users/benjaminadmin/Projekte/breakpilot-pwa/docker-compose.yml \
up -d studio-v2"
# 4. Testen
http://macmini:3001/dashboard-experimental
```
---
## Offene Punkte / Ideen
### Kurzfristig
- [ ] Echte Wetterdaten via API integrieren
- [ ] Kompass-Richtung dynamisch (GPS oder manuell)
- [ ] Klick auf Cards fuehrt zu Detailseiten
- [ ] Light Mode Support (aktuell nur Dark)
### Mittelfristig
- [ ] Drag & Drop fuer Card-Anordnung
- [ ] Weitere Widgets: Kalender, Termine, Erinnerungen
- [ ] Animierte Uebergaenge zwischen Seiten
- [ ] Sound-Feedback bei Interaktionen
### Langfristig
- [ ] Personalisierbare Widgets
- [ ] Dashboard als Standard-Startseite
- [ ] Mobile-optimierte Version
- [ ] Integration mit Apple Health / Fitness Daten
---
## Referenzen
- **Apple Weather App** (iOS) - Hauptinspiration
- **Dribbble Shot:** https://dribbble.com/shots/26339637-Smart-Home-Dashboard-Glassmorphism-UI
- **Design Tokens:** `/studio-v2/lib/spatial-ui/depth-system.ts`
---
## Aenderungshistorie
| Datum | Aenderung |
|-------|-----------|
| 2026-01-24 | FloatingMessage auf 4% Opacity reduziert |
| 2026-01-24 | Kompass, Balkendiagramm, Analog-Uhr hinzugefuegt |
| 2026-01-24 | Cards auf 8% Opacity reduziert |
| 2026-01-24 | Apple Weather Style implementiert |
| 2026-01-24 | Erstes Spatial UI System erstellt |

View File

@@ -0,0 +1,295 @@
# Multi-Agent Architektur - Entwicklerdokumentation
**Status:** Implementiert
**Letzte Aktualisierung:** 2025-01-15
**Modul:** `/agent-core/`
---
## 1. Übersicht
Die Multi-Agent-Architektur erweitert Breakpilot um ein verteiltes Agent-System basierend auf Mission Control Konzepten.
### Kernkomponenten
| Komponente | Pfad | Beschreibung |
|------------|------|--------------|
| Session Management | `/agent-core/sessions/` | Lifecycle & Recovery |
| Shared Brain | `/agent-core/brain/` | Langzeit-Gedächtnis |
| Orchestrator | `/agent-core/orchestrator/` | Koordination |
| SOUL Files | `/agent-core/soul/` | Agent-Persönlichkeiten |
---
## 2. Agent-Typen
| Agent | Aufgabe | SOUL-Datei |
|-------|---------|------------|
| **TutorAgent** | Lernbegleitung, Fragen beantworten | `tutor-agent.soul.md` |
| **GraderAgent** | Klausur-Korrektur, Bewertung | `grader-agent.soul.md` |
| **QualityJudge** | BQAS Qualitätsprüfung | `quality-judge.soul.md` |
| **AlertAgent** | Monitoring, Benachrichtigungen | `alert-agent.soul.md` |
| **Orchestrator** | Task-Koordination | `orchestrator.soul.md` |
---
## 3. Wichtige Dateien
### Session Management
```
agent-core/sessions/
├── session_manager.py # AgentSession, SessionManager, SessionState
├── heartbeat.py # HeartbeatMonitor, HeartbeatClient
└── checkpoint.py # CheckpointManager
```
### Shared Brain
```
agent-core/brain/
├── memory_store.py # MemoryStore, Memory (mit TTL)
├── context_manager.py # ConversationContext, ContextManager
└── knowledge_graph.py # KnowledgeGraph, Entity, Relationship
```
### Orchestrator
```
agent-core/orchestrator/
├── message_bus.py # MessageBus, AgentMessage, MessagePriority
├── supervisor.py # AgentSupervisor, AgentInfo, AgentStatus
└── task_router.py # TaskRouter, RoutingRule, RoutingResult
```
---
## 4. Datenbank-Schema
Die Migration befindet sich in:
`/backend/migrations/add_agent_core_tables.sql`
### Tabellen
1. **agent_sessions** - Session-Daten mit Checkpoints
2. **agent_memory** - Langzeit-Gedächtnis mit TTL
3. **agent_messages** - Audit-Trail für Inter-Agent Kommunikation
### Helper-Funktionen
```sql
-- Abgelaufene Memories bereinigen
SELECT cleanup_expired_agent_memory();
-- Inaktive Sessions bereinigen
SELECT cleanup_stale_agent_sessions(48); -- 48 Stunden
```
---
## 5. Integration Voice-Service
Der `EnhancedTaskOrchestrator` erweitert den bestehenden `TaskOrchestrator`:
```python
# voice-service/services/enhanced_task_orchestrator.py
from agent_core.sessions import SessionManager
from agent_core.orchestrator import MessageBus
class EnhancedTaskOrchestrator(TaskOrchestrator):
# Nutzt Session-Checkpoints für Recovery
# Routet komplexe Tasks an spezialisierte Agents
# Führt Quality-Checks via BQAS durch
```
**Wichtig:** Der Enhanced Orchestrator ist abwärtskompatibel und kann parallel zum Original verwendet werden.
---
## 6. Integration BQAS
Der `QualityJudgeAgent` integriert BQAS mit dem Multi-Agent-System:
```python
# voice-service/bqas/quality_judge_agent.py
from bqas.judge import LLMJudge
from agent_core.orchestrator import MessageBus
class QualityJudgeAgent:
# Wertet Responses in Echtzeit aus
# Nutzt Memory für konsistente Bewertungen
# Empfängt Evaluierungs-Requests via Message Bus
```
---
## 7. Code-Beispiele
### Session erstellen
```python
from agent_core.sessions import SessionManager
manager = SessionManager(redis_client=redis, db_pool=pool)
session = await manager.create_session(
agent_type="tutor-agent",
user_id="user-123"
)
```
### Memory speichern
```python
from agent_core.brain import MemoryStore
store = MemoryStore(redis_client=redis, db_pool=pool)
await store.remember(
key="student:123:progress",
value={"level": 5, "score": 85},
agent_id="tutor-agent",
ttl_days=30
)
```
### Nachricht senden
```python
from agent_core.orchestrator import MessageBus, AgentMessage
bus = MessageBus(redis_client=redis)
await bus.publish(AgentMessage(
sender="orchestrator",
receiver="grader-agent",
message_type="grade_request",
payload={"exam_id": "exam-1"}
))
```
---
## 8. Tests ausführen
```bash
# Alle Agent-Core Tests
cd agent-core && pytest -v
# Mit Coverage-Report
pytest --cov=. --cov-report=html
# Einzelne Module
pytest tests/test_session_manager.py -v
pytest tests/test_message_bus.py -v
```
---
## 9. Deployment-Schritte
### 1. Migration ausführen
```bash
psql -h localhost -U breakpilot -d breakpilot \
-f backend/migrations/add_agent_core_tables.sql
```
### 2. Voice-Service aktualisieren
```bash
# Sync zu Server
rsync -avz --exclude 'node_modules' --exclude '.git' \
/path/to/breakpilot-pwa/ server:/path/to/breakpilot-pwa/
# Container neu bauen
docker compose build --no-cache voice-service
# Starten
docker compose up -d voice-service
```
### 3. Verifizieren
```bash
# Session-Tabelle prüfen
psql -c "SELECT COUNT(*) FROM agent_sessions;"
# Memory-Tabelle prüfen
psql -c "SELECT COUNT(*) FROM agent_memory;"
```
---
## 10. Monitoring
### Metriken
| Metrik | Beschreibung |
|--------|--------------|
| `agent_session_count` | Anzahl aktiver Sessions |
| `agent_heartbeat_delay_ms` | Zeit seit letztem Heartbeat |
| `agent_message_latency_ms` | Nachrichtenlatenz |
| `agent_memory_count` | Gespeicherte Memories |
| `agent_routing_success_rate` | Erfolgreiche Routings |
### Health-Check-Endpunkte
```
GET /api/v1/agents/health # Supervisor Status
GET /api/v1/agents/sessions # Aktive Sessions
GET /api/v1/agents/memory/stats # Memory-Statistiken
```
---
## 11. Troubleshooting
### Problem: Session nicht gefunden
1. Prüfen ob Valkey läuft: `redis-cli ping`
2. Session-Timeout prüfen (default 24h)
3. Heartbeat-Status checken
### Problem: Message Bus Timeout
1. Redis Pub/Sub Status prüfen
2. Ziel-Agent registriert?
3. Timeout erhöhen (default 30s)
### Problem: Memory nicht gefunden
1. Namespace korrekt?
2. TTL abgelaufen?
3. Cleanup-Job gelaufen?
---
## 12. Erweiterungen
### Neuen Agent hinzufügen
1. SOUL-Datei erstellen in `/agent-core/soul/`
2. Routing-Regel in `task_router.py` hinzufügen
3. Handler beim Supervisor registrieren
4. Tests schreiben
### Neuen Memory-Typ hinzufügen
1. Key-Schema definieren (z.B. `student:*:progress`)
2. TTL festlegen
3. Access-Pattern dokumentieren
---
## 13. Referenzen
- **Agent-Core README:** `/agent-core/README.md`
- **Migration:** `/backend/migrations/add_agent_core_tables.sql`
- **Voice-Service Integration:** `/voice-service/services/enhanced_task_orchestrator.py`
- **BQAS Integration:** `/voice-service/bqas/quality_judge_agent.py`
- **Tests:** `/agent-core/tests/`
---
## 14. Änderungshistorie
| Datum | Version | Änderung |
|-------|---------|----------|
| 2025-01-15 | 1.0.0 | Initial Release |

View File

@@ -0,0 +1,99 @@
# Open Source Policy
## Lizenzprüfung (AUTOMATISCH BEI JEDER DEPENDENCY)
### Erlaubte Lizenzen ✅
| Lizenz | Typ | Kommerziell OK |
|--------|-----|----------------|
| MIT | Permissive | ✅ |
| Apache-2.0 | Permissive | ✅ |
| BSD-2-Clause | Permissive | ✅ |
| BSD-3-Clause | Permissive | ✅ |
| ISC | Permissive | ✅ |
| MPL-2.0 | Weak Copyleft | ✅ |
| LGPL-2.1 / LGPL-3.0 | Weak Copyleft | ✅ (nur linking) |
| CC0-1.0 | Public Domain | ✅ |
| Unlicense | Public Domain | ✅ |
### Verbotene Lizenzen ❌
| Lizenz | Grund |
|--------|-------|
| GPL-2.0 / GPL-3.0 | Copyleft - infiziert Projekt |
| AGPL-3.0 | Network Copyleft - SaaS-Killer |
| SSPL | Server Side Public License |
| BSL | Business Source License |
| "Non-Commercial" | Keine kommerzielle Nutzung |
| "Educational Only" | Nur für Bildung |
| Proprietary | Keine OSS |
---
## Workflow bei neuer Dependency
### 1. Vor dem Hinzufügen prüfen
```bash
# NPM Package
npm view <package> license
# Python Package
pip show <package> | grep License
# Go Module
go-licenses check <module>
```
### 2. Bei Unklarheit
- README.md des Projekts lesen
- LICENSE-Datei prüfen
- SPDX-Identifier suchen
- Im Zweifel: **NICHT verwenden**
### 3. Nach dem Hinzufügen
**SBOM aktualisieren:** https://macmini:3002/infrastructure/sbom
```bash
# SBOM generieren
cd /Users/benjaminadmin/Projekte/breakpilot-pwa
# Python
pip-licenses --format=json > sbom/python-licenses.json
# Node.js
npx license-checker --json > sbom/node-licenses.json
# Go
go-licenses csv ./... > sbom/go-licenses.csv
```
---
## Grenzfälle
### Dual-Licensed Packages
- Wenn MIT **oder** GPL angeboten wird → MIT wählen
- Dokumentieren welche Lizenz gewählt wurde
### Transitive Dependencies
- Auch indirekte Abhängigkeiten prüfen
- `npm ls`, `pip-tree`, `go mod graph`
### Fonts & Assets
- Google Fonts: ✅ (OFL)
- Font Awesome Free: ✅ (CC BY 4.0 / OFL / MIT)
- Icons8: ❌ (Attribution required, kompliziert)
---
## Checkliste bei PR/Commit
Wenn neue Dependencies hinzugefügt wurden:
- [ ] Lizenz ist in der Whitelist
- [ ] SBOM wurde aktualisiert
- [ ] Keine GPL/AGPL-Abhängigkeiten eingeschleppt
- [ ] Bei Dual-License: MIT/Apache gewählt

202
.claude/rules/testing.md Normal file
View File

@@ -0,0 +1,202 @@
# Test-Regeln
## Automatische Test-Erweiterung
**WICHTIG:** Bei JEDER Code-Änderung müssen entsprechende Tests erstellt oder aktualisiert werden!
## Wann Tests schreiben?
### IMMER wenn du:
1. **Neue Funktionen** erstellst → Unit Test
2. **Neue API-Endpoints** hinzufügst → Handler Test
3. **Bugs fixst** → Regression Test (der Bug sollte nie wieder auftreten)
4. **Bestehenden Code änderst** → Bestehende Tests anpassen
## Test-Struktur
### Go Tests (Consent Service)
**Speicherort:** Im gleichen Verzeichnis wie der Code
```
internal/
├── services/
│ ├── auth_service.go
│ └── auth_service_test.go ← Test hier
├── handlers/
│ ├── handlers.go
│ └── handlers_test.go ← Test hier
└── middleware/
├── auth.go
└── middleware_test.go ← Test hier
```
**Test-Namenskonvention:**
```go
func TestFunctionName_Scenario_ExpectedResult(t *testing.T)
// Beispiele:
func TestHashPassword_ValidPassword_ReturnsHash(t *testing.T)
func TestLogin_InvalidCredentials_Returns401(t *testing.T)
func TestCreateDocument_MissingTitle_ReturnsError(t *testing.T)
```
**Test-Template:**
```go
func TestFunctionName(t *testing.T) {
// Arrange
service := &MyService{}
input := "test-input"
// Act
result, err := service.DoSomething(input)
// Assert
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
if result != expected {
t.Errorf("Expected %v, got %v", expected, result)
}
}
```
**Table-Driven Tests bevorzugen:**
```go
func TestValidateEmail(t *testing.T) {
tests := []struct {
name string
email string
expected bool
}{
{"valid email", "test@example.com", true},
{"missing @", "testexample.com", false},
{"empty", "", false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := ValidateEmail(tt.email)
if result != tt.expected {
t.Errorf("Expected %v, got %v", tt.expected, result)
}
})
}
}
```
### Python Tests (Backend)
**Speicherort:** `/backend/tests/`
```
backend/
├── consent_client.py
├── gdpr_api.py
└── tests/
├── __init__.py
├── test_consent_client.py ← Tests für consent_client.py
└── test_gdpr_api.py ← Tests für gdpr_api.py
```
**Test-Namenskonvention:**
```python
class TestClassName:
def test_method_scenario_expected_result(self):
pass
# Beispiele:
class TestConsentClient:
def test_check_consent_valid_token_returns_status(self):
pass
def test_check_consent_expired_token_raises_error(self):
pass
```
**Test-Template:**
```python
import pytest
from unittest.mock import AsyncMock, patch, MagicMock
class TestMyFeature:
def test_sync_function(self):
# Arrange
input_data = "test"
# Act
result = my_function(input_data)
# Assert
assert result == expected
@pytest.mark.asyncio
async def test_async_function(self):
# Arrange
client = MyClient()
# Act
with patch("httpx.AsyncClient") as mock:
mock_instance = AsyncMock()
mock.return_value = mock_instance
result = await client.fetch_data()
# Assert
assert result is not None
```
## Test-Kategorien
### 1. Unit Tests (Höchste Priorität)
- Testen einzelne Funktionen/Methoden
- Keine externen Abhängigkeiten (Mocks verwenden)
- Schnell ausführbar
### 2. Integration Tests
- Testen Zusammenspiel mehrerer Komponenten
- Können echte DB verwenden (Test-DB)
### 3. Security Tests
- Auth/JWT Validierung
- Passwort-Hashing
- Berechtigungsprüfung
## Checkliste vor Abschluss
Vor dem Abschluss einer Aufgabe:
- [ ] Gibt es Tests für alle neuen Funktionen?
- [ ] Gibt es Tests für alle Edge Cases?
- [ ] Gibt es Tests für Fehlerfälle?
- [ ] Laufen alle bestehenden Tests noch? (`go test ./...` / `pytest`)
- [ ] Ist die Test-Coverage angemessen?
## Tests ausführen
```bash
# Go - Alle Tests
cd consent-service && go test -v ./...
# Go - Mit Coverage
cd consent-service && go test -cover ./...
# Python - Alle Tests
cd backend && source venv/bin/activate && pytest -v
# Python - Mit Coverage
cd backend && pytest --cov=. --cov-report=html
```
## Beispiel: Vollständiger Test-Workflow
Wenn du z.B. eine neue `GetUserStats()` Funktion im Go Service hinzufügst:
1. **Funktion schreiben** in `internal/services/stats_service.go`
2. **Test erstellen** in `internal/services/stats_service_test.go`:
```go
func TestGetUserStats_ValidUser_ReturnsStats(t *testing.T) {...}
func TestGetUserStats_InvalidUser_ReturnsError(t *testing.T) {...}
func TestGetUserStats_NoConsents_ReturnsEmptyStats(t *testing.T) {...}
```
3. **Tests ausführen**: `go test -v ./internal/services/...`
4. **Dokumentation aktualisieren** (siehe documentation.md)

View File

@@ -0,0 +1,205 @@
# Vokabel-Arbeitsblatt Generator - Entwicklerdokumentation
**Status:** Produktiv
**Letzte Aktualisierung:** 2026-02-08
**URL:** https://macmini/vocab-worksheet
---
## Uebersicht
Der Vokabel-Arbeitsblatt Generator ermoeglicht Lehrern:
- Schulbuchseiten (PDF/Bild) zu scannen
- Vokabeln automatisch per OCR zu extrahieren
- Druckfertige Arbeitsblaetter in verschiedenen Formaten zu generieren
---
## Architektur
```
Browser (studio-v2) klausur-service (Port 8086) PostgreSQL
│ │ │
│ POST /upload-pdf-info │ │
│ POST /process-single-page │ │
│ POST /generate │ │
│ POST /generate-nru │ ──── vocab_sessions ──────▶│
│ GET /worksheets/{id}/pdf │ ──── vocab_entries ───────▶│
│ │ ──── vocab_worksheets ────▶│
└────────────────────────────┘ │
```
---
## Arbeitsblatt-Formate
### Standard-Format
Klassisches Arbeitsblatt mit waehlbaren Uebungstypen:
- **Englisch → Deutsch**: Englische Woerter uebersetzen
- **Deutsch → Englisch**: Deutsche Woerter uebersetzen
- **Abschreibuebung**: Woerter mehrfach schreiben
- **Lueckensaetze**: Saetze mit Luecken ausfuellen
### NRU-Format (Neu: 2026-02-08)
Spezielles Format fuer strukturiertes Vokabellernen:
**Seite 1 (pro gescannter Seite): Vokabeltabelle**
| Englisch | Deutsch | Korrektur |
|----------|---------|-----------|
| word | (leer) | (leer) |
- Kind schreibt deutsche Uebersetzung
- Eltern korrigieren, Kind schreibt ggf. korrigierte Version
**Seite 2 (pro gescannter Seite): Lernsaetze**
| Deutscher Satz |
|-----------------------------------|
| (2 leere Zeilen fuer EN-Uebersetzung) |
- Deutscher Satz vorgegeben
- Kind schreibt englische Uebersetzung
**Automatische Trennung:**
- Einzelwoerter/Phrasen → Vokabeltabelle
- Saetze (enden mit `.!?` oder > 50 Zeichen) → Lernsaetze
---
## API-Endpoints
### Standard-Format
```
POST /api/v1/vocab/sessions/{session_id}/generate
Body: {
"worksheet_types": ["en_to_de", "de_to_en", "copy", "gap_fill"],
"title": "Vokabeln Unit 3",
"include_solutions": true,
"line_height": "normal" | "large" | "extra-large"
}
Response: { "id": "worksheet-uuid", ... }
```
### NRU-Format
```
POST /api/v1/vocab/sessions/{session_id}/generate-nru
Body: {
"title": "Vokabeltest",
"include_solutions": true,
"specific_pages": [1, 2] // optional, 1-indexed
}
Response: {
"worksheet_id": "uuid",
"statistics": {
"total_entries": 96,
"vocabulary_count": 75,
"sentence_count": 21,
"source_pages": [1, 2, 3],
"worksheet_pages": 6
},
"download_url": "/api/v1/vocab/worksheets/{id}/pdf",
"solution_url": "/api/v1/vocab/worksheets/{id}/solution"
}
```
### PDF-Download
```
GET /api/v1/vocab/worksheets/{worksheet_id}/pdf
GET /api/v1/vocab/worksheets/{worksheet_id}/solution
```
---
## Dateien
### Backend (klausur-service)
| Datei | Beschreibung |
|-------|--------------|
| `vocab_worksheet_api.py` | Haupt-API Router mit allen Endpoints |
| `nru_worksheet_generator.py` | NRU-Format HTML/PDF Generator |
| `vocab_session_store.py` | PostgreSQL Datenbankoperationen |
| `hybrid_vocab_extractor.py` | OCR-Extraktion (PaddleOCR + LLM) |
| `tesseract_vocab_extractor.py` | Tesseract OCR Fallback |
### Frontend (studio-v2)
| Datei | Beschreibung |
|-------|--------------|
| `app/vocab-worksheet/page.tsx` | Haupt-UI mit Template-Auswahl |
---
## Datenbank-Schema
```sql
-- Sessions
CREATE TABLE vocab_sessions (
id UUID PRIMARY KEY,
name VARCHAR(255),
status VARCHAR(50),
vocabulary_count INT,
source_language VARCHAR(10),
target_language VARCHAR(10),
created_at TIMESTAMP
);
-- Vokabeln
CREATE TABLE vocab_entries (
id UUID PRIMARY KEY,
session_id UUID REFERENCES vocab_sessions(id),
english TEXT,
german TEXT,
example_sentence TEXT,
source_page INT,
source_row INT,
source_column INT
);
-- Generierte Arbeitsblaetter
CREATE TABLE vocab_worksheets (
id UUID PRIMARY KEY,
session_id UUID REFERENCES vocab_sessions(id),
worksheet_types JSONB,
pdf_path VARCHAR(500),
solution_path VARCHAR(500),
generated_at TIMESTAMP
);
```
---
## Deployment
```bash
# 1. Backend synchronisieren
rsync -avz klausur-service/backend/ macmini:.../klausur-service/backend/
# 2. Frontend synchronisieren
rsync -avz studio-v2/app/vocab-worksheet/ macmini:.../studio-v2/app/vocab-worksheet/
# 3. Container neu bauen
ssh macmini "docker compose build --no-cache klausur-service studio-v2"
# 4. Container starten
ssh macmini "docker compose up -d klausur-service studio-v2"
```
---
## Erweiterung: Neue Formate hinzufuegen
1. **Backend**: Neuen Generator in `klausur-service/backend/` erstellen
2. **API**: Neuen Endpoint in `vocab_worksheet_api.py` hinzufuegen
3. **Frontend**: Format zu `worksheetFormats` Array in `page.tsx` hinzufuegen
4. **Doku**: Diese Datei aktualisieren
---
## Aenderungshistorie
| Datum | Aenderung |
|-------|-----------|
| 2026-02-08 | NRU-Format und Template-Auswahl hinzugefuegt |
| 2026-02-07 | Initiale Implementierung mit Standard-Format |