27. Wartung
Das System ist kein einmal eingerichteter Dauerläufer. Social-Media-Plattformen ändern ihre Oberflächen, Prompts altern, Sessions laufen ab, Inhalte wiederholen sich und Fehler sammeln sich an.
Wartung bedeutet hier:
Selektoren aktuell halten
Prompts kontrolliert weiterentwickeln
Dubletten entfernen
Fehler nacharbeiten
Sessions erneuern
Plattformänderungen dokumentieren
monatlich aufräumen
Die Wartung sollte nicht improvisiert erfolgen, sondern als wiederkehrende Routine.
27.1 Selektoren aktualisieren
Playwright-Adapter sind abhängig von der Weboberfläche der Plattformen.
Typische Bruchstellen:
Button-Texte ändern sich
Dialoge werden umgebaut
Upload-Felder ändern sich
Rollenbezeichnungen ändern sich
A/B-Tests verändern die Oberfläche
Sprache der Oberfläche wechselt
Selektoren dürfen deshalb nicht verstreut im Code stehen.
Schlecht:
page.get_by_role("button", name="Posten").click()
Besser:
@dataclass(frozen=True)
class LinkedInSelectorConfig:
start_post_buttons: list[str]
submit_buttons: list[str]
media_buttons: list[str]
LINKEDIN_SELECTOR_CONFIG = LinkedInSelectorConfig(
start_post_buttons=[
"Beitrag beginnen",
"Start a post",
],
submit_buttons=[
"Posten",
"Post",
],
media_buttons=[
"Bild hinzufügen",
"Medien hinzufügen",
"Foto hinzufügen",
"Add media",
"Add a photo",
],
)
Prüfroutine bei Fehler:
Screenshot öffnen
aktuellen Buttontext prüfen
Adapter-Selektor aktualisieren
Dry-Run ausführen
Screenshot prüfen
erst danach Live-Betrieb wieder aktivieren
Nach einer Selektoränderung:
python -m src.browser_session check linkedin --headed
python -m src.main publish-next
Live erst danach:
python -m src.main publish-next --live
27.2 Prompt-Versionen pflegen
Prompts dürfen nicht stillschweigend überschrieben werden, wenn sie bereits produktiv verwendet wurden.
Empfohlene Struktur:
prompts/
├── linkedin_post.v1.txt
├── linkedin_post.v2.txt
├── workshop_note.v1.txt
├── workshop_note.v2.txt
└── quality_check.v1.txt
Prompt-Registry:
@dataclass(frozen=True)
class PromptDefinition:
name: str
file_name: str
version: str
output_type: str
max_output_tokens: int
PROMPT_DEFINITIONS: dict[str, PromptDefinition] = {
"linkedin_post": PromptDefinition(
name="linkedin_post",
file_name="linkedin_post.v2.txt",
version="2.0.0",
output_type="text",
max_output_tokens=700,
),
}
Bei jeder Änderung festhalten:
Was wurde geändert?
Warum wurde es geändert?
Welche Beiträge waren betroffen?
Ab welchem Datum gilt die neue Version?
Beispiel:
2026-05-12
Prompt: workshop_note
Version: 2.0.0
Änderung: Verkaufsnahe Formulierungen stärker ausgeschlossen.
Grund: Mehrere Entwürfe klangen zu werblich.
Jeder PostDraft speichert weiterhin:
prompt_name
prompt_version
model
created_at
Damit bleibt nachvollziehbar, warum ältere Beiträge anders klingen.
27.3 Content-Dubletten bereinigen
Dubletten entstehen durch:
ähnliche Buchbeschreibungen
wiederholte Klassiker-Zitate
mehrere Beiträge zum selben Blogartikel
wiederkehrende Werkstatt-Themen
zu ähnliche KI-Formulierungen
Prüfung:
python -m src.main queue list --status draft
python -m src.main queue list --status published
Manuelle Dublettenbereinigung:
ähnliche Entwürfe anzeigen
schwächeren Entwurf ablehnen
besseren Entwurf freigeben
Themenliste anpassen
Prompt bei systematischer Wiederholung ändern
Beispiel für Dublettenprüfung als Wartungskommando:
class DuplicateMaintenanceService:
def find_possible_duplicates(
self,
posts: list[dict[str, object]],
max_similarity: float,
) -> list[tuple[str, str]]:
result: list[tuple[str, str]] = []
index = 0
while index < len(posts):
left_post = posts[index]
left_text = left_post.get("text")
left_id = left_post.get("id")
if isinstance(left_text, str) is False or isinstance(left_id, str) is False:
index += 1
continue
compare_index = index + 1
while compare_index < len(posts):
right_post = posts[compare_index]
right_text = right_post.get("text")
right_id = right_post.get("id")
if isinstance(right_text, str) is True and isinstance(right_id, str) is True:
similarity = self._similarity(left_text, right_text)
if similarity >= max_similarity:
result.append(
(
left_id,
right_id,
)
)
compare_index += 1
index += 1
return result
def _similarity(self, left_text: str, right_text: str) -> float:
left_words = set(left_text.lower().split())
right_words = set(right_text.lower().split())
if len(left_words) == 0 and len(right_words) == 0:
return 1.0
intersection = left_words.intersection(right_words)
union = left_words.union(right_words)
return len(intersection) / len(union)
27.4 Fehlgeschlagene Posts prüfen
Fehlgeschlagene Posts dürfen nicht liegen bleiben.
Prüfen:
python -m src.main queue list --status failed
python -m src.main queue list --status blocked
python -m src.main logs errors --limit 50
Für jeden Fehler:
Screenshot öffnen
Fehlermeldung lesen
Ursache klassifizieren
Status manuell entscheiden
Selektor korrigieren oder Beitrag ablehnen
Dry-Run wiederholen
Fehlerarten:
failed: technischer Fehler, eventuell wiederholbar
blocked: kritischer Plattformzustand, nicht automatisch wiederholen
Beispiele:
Post button not found → Selektor prüfen
Image file does not exist → Bildpfad korrigieren
Login required → Session erneuern
CAPTCHA detected → manuell prüfen, Plattform pausieren
Empfohlenes Vorgehen bei blocked:
Plattform-Kill-Switch aktivieren
Session sichtbar prüfen
Screenshot prüfen
keine Live-Aktion ausführen
nach manueller Klärung Dry-Run
Kill-Switch erst danach deaktivieren
27.5 Session erneuern
Sessions laufen ab oder werden durch Plattformen ungültig.
Symptome:
Login required
checkpoint
security verification
leerer Feed
unerwartete Login-Seite
Session erneuern:
python -m src.browser_session login linkedin
python -m src.browser_session check linkedin --headed
Für Instagram:
python -m src.browser_session login instagram
python -m src.browser_session check instagram --headed
Für Facebook:
python -m src.browser_session login facebook
python -m src.browser_session check facebook --headed
Nach Session-Erneuerung:
python -m src.main publish-next
Erst wenn der Dry-Run sauber ist:
python -m src.main publish-next --live
Session-Dateien bleiben sensibel:
storage/sessions/linkedin.json
storage/sessions/instagram.json
storage/sessions/facebook.json
Rechte prüfen:
chmod 700 storage/sessions
chmod 600 storage/sessions/*.json
27.6 Plattformänderungen dokumentieren
Jede relevante Plattformänderung wird dokumentiert.
Datei:
docs/platform_changes.md
Beispiel:
# Plattformänderungen
## 2026-05-12 LinkedIn
Problem:
Der Button „Beitrag beginnen“ wurde in der deutschen Oberfläche zeitweise nicht gefunden.
Beobachtung:
Screenshot: storage/screenshots/linkedin/draft_20260512_001_failed.png
Änderung:
Zusätzlicher Buttontext ergänzt:
- Start a post
Betroffene Datei:
src/platforms/linkedin_publisher.py
Prüfung:
Dry-Run erfolgreich am 2026-05-12.
Minimal festhalten:
Datum
Plattform
Symptom
Screenshot
geänderte Datei
neuer Selektor
Dry-Run-Ergebnis
Das verhindert, dass dieselben Fehler später erneut analysiert werden müssen.
27.7 Monatsroutine
Einmal im Monat sollte das System systematisch geprüft werden.
Checkliste:
1. Queue prüfen
2. Fehler prüfen
3. blockierte Beiträge prüfen
4. Logs rotieren oder archivieren
5. Screenshots archivieren
6. Sessions testen
7. Prompts prüfen
8. Dubletten prüfen
9. Reports auswerten
10. Plattformänderungen dokumentieren
Kommandos:
python -m src.main queue status
python -m src.main queue list --status failed
python -m src.main queue list --status blocked
python -m src.main logs errors --limit 100
python -m src.main report weekly --start 2026-05-01 --end 2026-05-31
Screenshots archivieren:
mkdir -p storage/archive/screenshots/2026-05
find storage/screenshots -type f -name "*.png" -mtime +30 -exec mv {} storage/archive/screenshots/2026-05/ \;
Logs archivieren:
mkdir -p storage/archive/logs/2026-05
cp storage/logs/events.jsonl storage/archive/logs/2026-05/events.jsonl
cp storage/logs/errors.jsonl storage/archive/logs/2026-05/errors.jsonl
cp storage/logs/openai_usage.jsonl storage/archive/logs/2026-05/openai_usage.jsonl
Danach neue Logdateien anlegen:
: > storage/logs/events.jsonl
: > storage/logs/errors.jsonl
: > storage/logs/openai_usage.jsonl
Vor dem Leeren der Logs muss das Archiv geprüft sein.
Monatsnotiz:
# Monatswartung 2026-05
Queue:
- draft: 4
- approved: 1
- published: 18
- failed: 2
- blocked: 0
Änderungen:
- LinkedIn-Selektor ergänzt
- Instagram-Caption-Prompt verschärft
- 3 Dubletten abgelehnt
Offen:
- Facebook-Bildupload erneut prüfen
Ergebnis dieses Kapitels
Die Wartung umfasst jetzt:
Selektorpflege
Prompt-Versionierung
Dublettenbereinigung
Fehlernacharbeit
Session-Erneuerung
Dokumentation von Plattformänderungen
monatliche Betriebsprüfung
Damit bleibt das System kontrollierbar, auch wenn Plattformen ihre Oberflächen ändern oder Inhalte sich wiederholen.
0 Kommentare