Alfred  ·  Operations Guide

Operations Guide

Alfred starten, stoppen, überwachen — und verstehen, was er aufzeichnet.

Alfred besteht aus vier Diensten: Redis (Caching & Session-Replay), Cortex (Backend auf Port 3000), Monitor (Hintergrund-Preprocessing) und Face (Angular Frontend auf Port 4200). Alle Steuerscripts liegen in scripts/.

# Redis starten (Docker, läuft dauerhaft)
./scripts/start-redis.sh

# Cortex starten
./scripts/start-cortex.sh # Vordergrund
./scripts/start-cortex.sh -d # Hintergrund (log: data/logs/cortex.log)
./scripts/start-cortex.sh -t # Hintergrund + tail (Ctrl+C beendet nur tail)

# Monitor starten (Mail-Analyse im Hintergrund)
./scripts/start-monitor.sh # Vordergrund
./scripts/start-monitor.sh -d # Hintergrund (log: data/logs/monitor.log)
./scripts/start-monitor.sh -t # Hintergrund + tail

# Face starten
./scripts/start-face.sh # Vordergrund
./scripts/start-face.sh -d # Hintergrund (log: data/logs/face.log)

# Alles zusammen (Cortex + Face, Vordergrund)
./scripts/start-dev.sh # Ctrl+C beendet beides
# Status aller Dienste prüfen (farbig)
./scripts/status.sh

# Einzeln prüfen
./scripts/cortex-up-check.sh # → cortex running (PID 12345)
./scripts/face-up-check.sh # → face running (PID 12346)

# Stoppen
./scripts/stop-cortex.sh # Kill by process title alfred:cortex
./scripts/stop-monitor.sh # Kill by process title alfred:monitor
./scripts/stop-face.sh # Kill by ng serve on port 4200
Prozess-Erkennung: Cortex setzt process.title = 'alfred:cortex', Monitor setzt process.title = 'alfred:monitor' beim Start. Die Stop- und Check-Scripts nutzen pgrep -f, um den Prozess zuverlässig zu finden — kein PID-Merken nötig.
status.sh: Zeigt den Status aller Dienste auf einen Blick — Cortex, Face, Monitor, Redis, Maildev, Ollama (kitt), OCR (kitt), GLiNER (karr) und Chat Bridge.

Der Monitor ist ein eigenständiger Hintergrundprozess, der eingehende E-Mails automatisch analysiert, bevor der Nutzer sie sieht. Er läuft parallel zum Cortex und schreibt Ergebnisse nach Redis.

IMAP Pollalle 60s
RecognitionLayer 0 + Layer 1
OCR + Extraktionbei Match mit Anhang
Redis Cachepreprocess:mail:{uid}
monitor:mail:{uid}
Recognition-Ergebnis: Szenario-Name, Konfidenz (high/medium/low/none), Layer
preprocess:mail:{uid}
Vollständige Extraktion: Workflow, alle Params, fieldResults mit OCR-Qualität
monitor:processing:{uid}
Flag während der Analyse — Cortex zeigt „wird vorbereitet“ wenn aktiv
# Monitor-Zustand in Redis prüfen
./scripts/test/test-redis.sh monitor

# Monitor zurücksetzen (alle Ergebnisse löschen, Neuanalyse erzwingen)
./scripts/test/reset-monitor.sh
# Danach Monitor neustarten (in-memory analyzedUids bleibt sonst bestehen)
Nach Szenario-Änderungen: Wenn Szenarien umbenannt oder gelöscht werden, müssen alte Monitor-Ergebnisse geflusht werden. Die gecachten Ergebnisse referenzieren den alten Szenario-Namen. Nutze ./scripts/test/reset-monitor.sh und starte den Monitor neu.

Alfred schreibt auf drei Ebenen mit — jede Ebene hat einen anderen Zweck und eine andere Lebensdauer.

Workflow-Eventstep, confirm, error
Dual Writecortex/service/persistence.ts
Redis Streamsession:{id}
+
Dateisystemdata/runs & data/audit
Ebene Speicherort Format Lebensdauer Zweck
Run Records data/runs/{ts}-{workflow}.json JSON Dauerhaft Kompletter Lauf inkl. aller Events — für Operations-Dashboard, KPIs, Nachvollziehbarkeit
Audit Log data/audit/audit-{YYYY-MM-DD}.jsonl JSONL (1 Event pro Zeile) Dauerhaft Chronologisches Protokoll aller Aktionen — für Compliance, Audit-Dashboard
Redis Streams session:{id}, audit:* Redis Stream 1 Stunde TTL Session-Replay bei F5, Live-Dashboard, schnelle Abfragen
Process Logs data/logs/cortex.log, face.log Stdout/Stderr Bis überschrieben Debugging, Startprobleme, Request-Logs
Dual-Write-Prinzip: Jeder Event wird sowohl nach Redis als auch ins Dateisystem geschrieben. Fällt Redis aus, funktioniert Alfred weiter — nur Session-Replay (F5) ist dann nicht verfügbar. Bei Redis-Neustart greift die automatische Reconnection.

Pro abgeschlossenem Workflow-Lauf entsteht eine JSON-Datei. Sie enthält den kompletten Lauf mit allen Events und Ergebnissen.

runId
Eindeutige ID des Laufs (UUID)
workflow
Name des YAML-Workflows, z.B. stadtwerke-stromanmeldung
params
Eingabeparameter (Dokument-Pfad, Nutzer-Eingaben)
startedAt / completedAt
ISO-8601-Zeitstempel — daraus berechnet sich durationMs
status
completed | failed | cancelled
events[]
Array aller AuditEntry-Objekte dieses Laufs (identisch zu den Einträgen im Audit-Log)
result / error
Ergebnis bei Erfolg bzw. Fehler-Details bei Fehlschlag

Zusätzlich wird der Run als Redis Hash unter run:{runId} gespeichert, was schnelle Lookups ohne Dateisystem-Zugriff ermöglicht.


Das Audit-Log ist ein append-only JSONL-File, das täglich rotiert. Jede Zeile ist ein eigenständiger JSON-Eintrag — ideal für grep, jq und Streaming-Verarbeitung.

Event-Typ Beschreibung Details-Felder
run-started Workflow-Lauf gestartet workflow, params
step-completed Ein Schritt im Workflow abgeschlossen step, duration
confirm-requested Bestätigung vom Nutzer angefordert fields, confidence
confirm-accepted Nutzer hat bestätigt accepted fields
confirm-cancelled Nutzer hat abgebrochen
field-edited Nutzer hat ein Feld korrigiert field, before, after
correction-submitted Korrektur nach Fehler eingereicht field, value
answer-given Nutzer hat eine Frage beantwortet question, answer
timeout-continue Nutzer hat nach Timeout fortgesetzt
timeout-abort Timeout-Abbruch
run-completed Workflow erfolgreich abgeschlossen durationMs, result
run-failed Workflow mit Fehler beendet error
run-cancelled Workflow abgebrochen
mail-trigger E-Mail hat Workflow ausgelöst subject, from, workflow
# Audit-Log lesen cat data/audit/audit-2026-03-11.jsonl | jq . # Nur fehlgeschlagene Runs finden grep '"run-failed"' data/audit/audit-2026-03-11.jsonl | jq . # Alle Korrekturen eines bestimmten Runs grep '"field-edited"' data/audit/audit-*.jsonl | jq 'select(.runId == "abc-123")'

Redis dient als schneller Puffer für Live-Sessions. Wenn der Nutzer während eines Laufs F5 drückt, fragt die Face den Cortex nach den bisherigen Events — diese kommen aus dem Redis Stream.

Browser F5face reconnect
GET /api/session/:id/eventscortex endpoint
Redis Streamsession:{id}
Chat-Replayalle Events rekonstruiert
session:{id}
Alle SSE-Events einer Session, 1h TTL. Enthält Screenshots als Datei-URLs (nicht base64).
audit:daily:{date}
Tages-Audit-Stream — Spiegel der JSONL-Datei, für schnelle Dashboard-Abfragen.
audit:run:{runId}
Alle Audit-Events eines einzelnen Runs — für die Detail-Ansicht.
run:{runId}
Run-Record als Redis Hash — schneller Lookup ohne Dateisystem.
# Redis-Keys anzeigen docker exec alfred-redis redis-cli KEYS "session:*" docker exec alfred-redis redis-cli KEYS "run:*" docker exec alfred-redis redis-cli KEYS "audit:*" # Session-Events lesen docker exec alfred-redis redis-cli XRANGE "session:abc-123" - + # Redis komplett leeren (Vorsicht!) docker exec alfred-redis redis-cli FLUSHDB

Während eines Workflow-Laufs erstellt der Web-Actor Playwright-Screenshots. Diese werden nicht als base64 in den SSE-Stream geschrieben, sondern auf Disk externalisiert.

Speicherort
data/temp/{sessionId}/screenshot-{n}.jpg
HTTP-Zugriff
GET /api/screenshot/{sessionId}/{fileName}
Ablauf
broadcastToSseClients() erkennt base64 im Event, speichert als Datei, ersetzt mit URL

Die Angular-Face bietet vier Dashboards, die sich aus den verschiedenen Datenquellen speisen.

Dashboard Route Datenquelle Inhalt
Operations /operations data/runs/ KPI-Karten (Anzahl Runs, Erfolgsrate, Durchschnittsdauer), Workflow-Breakdown, Runs-Tabelle
Live /active SSE-Stream Laufende Workflows in Echtzeit, verschwindet nach Abschluss
Szenarien /scenarios data/scenarios/ Katalog aller Szenarien, Health-Badges (grün/rot/unbekannt), Prüfen-Button
Audit /audit data/audit/ Chronologisches Event-Log, filterbar

Jedes Szenario kann automatisch geprüft werden, wenn alle Pflichtfelder ein verificationValue im YAML haben. Der Health-Check startet einen headless Playwright-Lauf und prüft auf Validierungsfehler und Submit-Button-Status.

POST /api/scenarios/:name/verifyTrigger
Playwrightheadless fill
Redisscenario:health:{name}
scenario:health:{name}
Status green oder red, Zeitstempel, Fehlerdetails
Health Gate
Vor jeder Workflow-Ausführung wird der Health-Status geprüft. Bei red wird die Ausführung blockiert.
verificationValue
Known-good Testwert im YAML — wird von der Extension nach erfolgreichem Replay geschrieben.
# Health-Status prüfen
./scripts/test/test-redis.sh health

# Health-Status löschen
./scripts/test/test-redis.sh flush-health

# Health-Gate testen
./scripts/test/test-health-gate.sh

Zwei Scripts zum Zurücksetzen von Laufzeitdaten. Beide löschen niemals Quellcode oder Konfiguration.

# Nur Redis leeren (Monitor-Ergebnisse, Sessions, Runs)
./scripts/flush-redis.sh

# Komplett-Reset: Redis + Dateisystem (runs/, audit/, logs/, temp/)
./scripts/flush-all.sh
flush-all.sh löscht alle Run Records und Audit-Logs unwiderruflich. Nur verwenden, wenn ein vollständig frischer Start gewünscht ist.

Alle Test-Scripts liegen in scripts/test/ und sind ohne interaktive Eingabe ausführbar.

Script Zweck Benötigt
test-redis.sh Redis-Keys inspizieren: Übersicht, Health-Status, Suche nach Pattern Redis
trace-run.sh Alle Daten eines Runs finden — Files, Audit, Logs, Redis Redis
test-recognition.sh Szenario-Erkennung testen: Phrase eingeben, Match prüfen Cortex
test-preprocessing.sh Monitor-Preprocessing-Pipeline prüfen: Flags und Ergebnisse in Redis Cortex, Redis
test-health-gate.sh Health-Gate testen: Szenario auf red setzen, Blockierung prüfen Cortex, Redis
test-forms.sh Extraction-Tests für ausgefüllte Formular-Fixtures Node.js
prompt-alfred.sh E2E: Prompt an Face senden (Playwright), Antwort erfassen Cortex, Face, Playwright
reset-monitor.sh Monitor-Ergebnisse in Redis löschen (Neuanalyse erzwingen) Redis
send-test-mail.py Test-Mail mit Anhängen an Maildev senden Maildev (SMTP :1025)
# Beispiel: Recognition testen
./scripts/test/test-recognition.sh "Verarbeite die Stromanmeldung"

# Beispiel: Einen Run nachverfolgen
./scripts/test/trace-run.sh stromanmeldung

Bei mail-getriggerten Workflows verhindert ein Redis NX Lock, dass dasselbe Szenario für dieselbe Mail doppelt ausgeführt wird.

run:lock:{scenario}:{uid}
Redis-Key mit NX (set-if-not-exists). Wird bei done/cancel/error freigegeben.
Lebenszyklus
acquire → running → release (done | cancel | error)

Die Browser-Extension sammelt Interaktionsdaten (Klicks, Feldeingaben, Idle-Zeiten, Netzwerk-Calls, Submit-Ergebnisse) und sendet sie an POST /api/learning/events. Pro Session entsteht eine JSONL-Datei in data/logs/learning/.

Domain-Allowlist
Der Logger aktiviert sich nur auf freigegebenen Domains. Konfiguriert in extension/content/learning-logger.jsALLOWED_DOMAINS.
Aktuell: localhost.
Für Kunden-Deployments die jeweilige Domain ergänzen (z.B. app.customer.de). Subdomains werden automatisch erkannt.
Event-Typen (15)
session_start, session_end, page_context, field_focus, field_blur, field_paste, click, submit, navigation, visibility, idle_start, idle_end, network_call, step_advance, deviation
Netzwerk-Interception
network-interceptor.js läuft im MAIN-World-Kontext und wrapped fetch + XMLHttpRequest. Loggt nur URL-Pattern, Methode, Status, Dauer — keine Request/Response-Bodies. Nur aktiv wenn Learning Mode eingeschaltet ist. Eigene Calls (/api/learning/) und bekannte Tracker werden gefiltert.
Logs einsehen
ls data/logs/learning/ — eine Datei pro Session.
Schnellcheck: jq -r '.type' data/logs/learning/DATEI.jsonl | sort | uniq -c | sort -rn
Validierung: ./scripts/test/test-learning-logger.sh
Flush-Intervall
Events werden alle 5 Sekunden gesendet (konfigurierbar: FLUSH_INTERVAL_MS). Bei Cortex-Ausfall werden Events im Speicher gehalten und beim nächsten erfolgreichen Flush nachgeliefert.
Redis ist down
Alfred läuft weiter — File-Fallback greift. Nur F5-Replay funktioniert nicht. Nach docker start alfred-redis verbindet Cortex sich automatisch neu.
Port 3000 belegt
./scripts/cortex-up-check.sh — falls alter Prozess läuft: ./scripts/stop-cortex.sh
Port 4200 belegt
./scripts/face-up-check.sh — falls alter Prozess läuft: ./scripts/stop-face.sh
Monitor erkennt Mails nicht
Szenarien umbenannt? ./scripts/test/reset-monitor.sh + Monitor neustarten. Redis-Keys prüfen: ./scripts/test/test-redis.sh monitor
Health Gate blockiert
Szenario-Health ist red. Prüfen: ./scripts/test/test-redis.sh health. Zum Löschen: ./scripts/test/test-redis.sh flush-health
Dashboard leer
Prüfen: existieren Dateien in data/runs/ und data/audit/? Wenn nicht, wurde noch kein Workflow ausgeführt.
Logs einsehen
tail -f data/logs/cortex.log, data/logs/monitor.log bzw. data/logs/face.log (nur bei detached-Start)
Alles zurücksetzen
./scripts/flush-all.sh — Redis + alle Laufzeitdaten. Frischer Start.