# Plan: Vereinheitlichung aller Artikel-Cronjobs für brettspiel-news.de

> **Ziel:** Alle 10 artikelproduzierenden Cronjobs liefern konsistent fehlerfreie HTML-Artikel ohne manuelle Nachkorrektur. Kein Job publiziert ohne Qualitätsnachweis nach Joomla.

**Stand:** 22. Juni 2026 | **Autor:** Basti (CvD Redaktion)

---

## 1. Bestandsaufnahme: Alle Artikel-Jobs

| # | Job-ID | Name | Zeit | Skills | Publiziert? | Probleme |
|---|---|---|---|---|---|---|
| 1 | `5399bf408bd1` | Nächtlicher Deal-Artikel | täglich 03:00 | amazon-brettspiel-deals, deal-grafik-workflow | ✅ Joomla | Read-More doppelt, Bild manchmal falsch |
| 2 | `a3a4e5236143` | Amazon-Deals Montag | Mo 09:00 | amazon-brettspiel-deals | ✅ Joomla | Read-More doppelt |
| 3 | `a506d9cea05d` | Amazon-Deals Donnerstag | Do 09:00 | amazon-brettspiel-deals | ✅ Joomla | Noch nie gelaufen |
| 4 | `5666a1b8ed83` | Samstag: Alle Shops | Sa 09:00 | partner-shop-links, amazon-brettspiel-deals | ✅ Joomla | Noch nie gelaufen |
| 5 | `ddfd96310e95` | Sonntag: Kinderspiele | So 09:00 | amazon-brettspiel-deals | ✅ Joomla | Read-More doppelt |
| 6 | `2c158c141090` | Sonntag: Crowdfunding | So 09:00 | web-research, journalistic-article-writing | ❌ Nur HTML | URLs geraten, alte Daten, kein Bild |
| 7 | `6e6eb5bd0cc8` | BGA Weekly Update | Di 09:00 | bga-news-scraper, journalistic-article-writing | ✅ Joomla | Unbekannt |
| 8 | `f3c583a4779f` | Fantasywelt Vorbest. (Fr) | Fr 07:00 | fantasywelt-neuheiten | ✅ Joomla | Unbekannt |
| 9 | `32839f09c412` | Fantasywelt Neuheiten (Mi) | Mi 09:00 | fantasywelt-neuheiten | ❌ Telegram | Nur Stats |
| 10 | `a35a31dbdf1c` | Fantasywelt Vorbest. Fr | Fr 09:00 | fantasywelt-neuheiten | ❌ Telegram | Nur Stats |

---

## 2. Wiederkehrende Fehler (systematisch)

### 🔴 KRITISCH: Doppelter Read-More-Break
**Symptom:** `<hr id="system-readmore" />` gefolgt von `<br>` → Joomla zeigt zwei Trennlinien.
**Ursache:** Das HTML-Template oder der Prompt enthält ein `<br>` direkt nach dem Read-More.
**Betroffene Jobs:** 1, 2, 3, 4, 5, 6, 7

### 🔴 KRITISCH: Fremd-Content nach Artikel-Ende
**Symptom:** QC-Zeile, Meta-Notizen oder Prompt-Reste erscheinen unter dem Artikel.
**Ursache:** `article_server.py` strippt nicht alle internen Marker. Sub-Agenten schreiben Debug-Output in den Body.
**Betroffene Jobs:** Alle

### 🔴 KRITISCH: Bild-Format `image_intro`
**Symptom:** Bild wird nicht angezeigt, obwohl API "200" meldet.
**Ursache:** `image_intro` muss Format `images/.../file.jpg#joomlaImage://local-images/Spiele/.../file.jpg` haben. Absolute HTTPS-URLs werden von Joomla-Frontend ignoriert.
**Betroffene Jobs:** Alle die per API publizieren

### 🟠 MITTEL: Geratene/veraltete URLs
**Symptom:** Kampagnen-Links führen zu 404.
**Ursache:** URLs werden aus Projektnamen konstruiert statt aus echten Quellen (GF-API, EBG-Scraping).
**Betroffene Jobs:** 6 (Crowdfunding)

### 🟠 MITTEL: Umlaut-Verlust durch write_file
**Symptom:** ä→a, ö→o, ü→u, ß→ss.
**Ursache:** Encoding-Bug in `write_file` bei HTML-Dateien.
**Betroffene Jobs:** Alle die write_file nutzen

### 🟡 NIEDRIG: QC fehlt vor Joomla-Publish
**Symptom:** Fehlerhafte Artikel gehen live ohne menschliche Sichtung.
**Ursache:** Jobs publizieren direkt, keine Quality-Gate.
**Betroffene Jobs:** 1, 2, 3, 4, 5, 7, 8

---

## 3. Der einheitliche Standard

**JEDER Artikel-Job MUSS ab sofort diese Checkliste erfüllen:**

### Phase A: Daten beschaffen
- [ ] A1: Nur aus verifizierten Quellen (APIs, Scraping mit wget+Firefox-UA)
- [ ] A2: URLs NIE raten — entweder aus API (`projectHomeUrl`) oder Scraping
- [ ] A3: Daten mit Zeitstempel speichern (für Debugging)

### Phase B: Artikel schreiben
- [ ] B1: Template `templates/article.html` aus journalistic-article-writing Skill
- [ ] B2: `<hr id="system-readmore" />` NACH Absatz 1 — **KEIN `<br>` davor oder danach**
- [ ] B3: `<p class="meta">` (NICHT `<div>`) — sonst kein Index-Eintrag
- [ ] B4: Meta-Description + Keywords im `<head>`
- [ ] B5: Quellen-Überschrift: `<span style="text-decoration: underline;"><strong>Quellen</strong></span>` (NICHT `<h2>`)
- [ ] B6: KEINE Emojis, KEINE Icons
- [ ] B7: Genderneutral (Partizipien)
- [ ] B8: Spieletitel in `<strong>`
- [ ] B9: ALLE Links `target="_blank"`
- [ ] B10: KEINE Meta-Zeile im Body (Titel, Datum, Lesezeit)

### Phase C: Umlaut-Korrektur
- [ ] C1: `python3 fix_umlauts.py artikel_*.html`
- [ ] C2: Manueller Zweitpass: Titel + erste 2 Absätze + Quellen prüfen
- [ ] C3: `grep -n 'a\b\|o\b\|u\b'` auf verdächtige Wörter ohne Umlaut

### Phase D: Read-More-Verifikation (NEU)
- [ ] D1: `grep -c 'system-readmore' artikel_*.html` → muss GENAU 1 sein
- [ ] D2: `grep -A1 'system-readmore' artikel_*.html` → nächste Zeile darf KEIN `<br>` enthalten
- [ ] D3: NACH dem Read-More: erstes Zeichen muss `<h2>` oder `<p>` sein, nicht `<br>`

### Phase E: Artikel-Ende-Verifikation (NEU)
- [ ] E1: Letzte 5 Zeilen prüfen: kein Debug-Output, keine Prompt-Reste
- [ ] E2: Artikel endet mit `</article>\n</body>\n</html>` — nichts dahinter
- [ ] E3: QC-Zeile MUSS in `<p class="qc">` gewrappt sein (wird von article_server gestrippt)

### Phase F: Bild (nur wenn publiziert wird)
- [ ] F1: Cover-Bild existiert unter `/home/hermes/workspace/media/`
- [ ] F2: In `article_images.json` gemappt
- [ ] F3: `image_intro` Format: `images/.../file.jpg#joomlaImage://local-images/Spiele/.../file.jpg`
- [ ] F4: `image_fulltext` GLEICHES Format

### Phase G: Delivery
- [ ] G1: **NUR HTML in Workspace schreiben** (`/home/hermes/workspace/artikel_*.html`)
- [ ] G2: **KEIN Joomla-Publish** ohne explizite Freigabe
- [ ] G3: Basti informieren: Dateiname, Kampagnen-Anzahl / Deal-Anzahl, Pfad

---

## 4. Umsetzungsplan (5 Schritte)

### Schritt 1: Template fixen (sofort)
**Datei:** `/home/hermes/.hermes/skills/creative/journalistic-article-writing/templates/article.html`

**Änderungen:**
- `<hr id="system-readmore" />` **ohne** folgendes `<br>` (Zeile prüfen + fixen)
- QC-Zeile als `<p class="qc">` markieren (wird von article_server gestrippt)
- Letzte Zeile vor `</article>` sicherstellen: kein Fremd-Content

**Verifikation:**
```bash
grep -A1 'system-readmore' templates/article.html
# Darf KEIN <br> in der Folgezeile zeigen
```

### Schritt 2: article_server.py Stripping verbessern (heute)
**Datei:** `/home/hermes/workspace/article_server.py`

**Änderungen:**
- Funktion `_strip_internal_markers()` extrahieren
- Stripping-Reihenfolge: H1 → Meta-Zeile → QC-Zeile → Leerzeilen am Ende
- Test mit einem bekannten Problem-Artikel

### Schritt 3: Alle Job-Prompts vereinheitlichen (heute)
**Für JEDEN Artikel-Job** den Prompt ergänzen um:
```
WICHTIGE REGELN (bei Nichtbeachtung wird Artikel verworfen):
- <hr id="system-readmore" /> NACH Absatz 1 — KEIN <br> davor oder danach
- KEINE Meta-Zeile im Body
- Letzte Zeile vor </article> ist der Quellen-Abschnitt — nichts danach
- QC-Hinweis NUR in <p class="qc"> (wird automatisch entfernt)
```

### Schritt 4: Read-More-Verifikations-Script (heute)
**Neu:** `/home/hermes/workspace/verify_article.sh`

```bash
#!/bin/bash
# Verifies article HTML meets all standards
# Usage: ./verify_article.sh artikel_*.html
# Exit 0 = OK, Exit 1 = Fehler

FILE=$1
ERRORS=0

# Check 1: Exactly one read-more
COUNT=$(grep -c 'system-readmore' "$FILE")
if [ "$COUNT" != "1" ]; then
    echo "❌ Read-More count: $COUNT (muss 1 sein)"
    ERRORS=$((ERRORS+1))
fi

# Check 2: No <br> after read-more
if grep -A1 'system-readmore' "$FILE" | grep -q '<br>'; then
    echo "❌ <br> nach Read-More gefunden"
    ERRORS=$((ERRORS+1))
fi

# Check 3: Ends with </html>
if ! tail -1 "$FILE" | grep -q '</html>'; then
    echo "❌ Datei endet nicht mit </html>"
    ERRORS=$((ERRORS+1))
fi

# Check 4: Meta line is <p> not <div>
if grep -q '<div class="meta">' "$FILE"; then
    echo "❌ <div class=\"meta\"> statt <p class=\"meta\">"
    ERRORS=$((ERRORS+1))
fi

# Check 5: No emojis
if grep -qP '[\x{1F300}-\x{1F9FF}]' "$FILE"; then
    echo "❌ Emojis gefunden"
    ERRORS=$((ERRORS+1))
fi

[ $ERRORS -eq 0 ] && echo "✅ $FILE: Alle Checks bestanden"
exit $ERRORS
```

### Schritt 5: Quality-Gate vor Joomla-Publish (diese Woche)
**Workflow-Änderung:**
1. Job schreibt HTML → Workspace
2. `verify_article.sh` läuft automatisch
3. Bei Fehler: Job meldet Fehler an Basti, KEIN Publish
4. Bei Erfolg: Artikel auf Article-Server → Daniel reviewed → Daniel published

---

## 5. Job-für-Job-Änderungen

| Job | Prompt-Update | Kein Joomla | verify_article | Bild-Check |
|---|---|---|---|---|
| Nächtlicher Deal | ✅ | ❌ (läuft schon live) | ✅ | ✅ |
| Amazon Mo | ✅ | ❌ (läuft schon live) | ✅ | ✅ |
| Amazon Do | ✅ | ❌ | ✅ | ✅ |
| Samstag Shops | ✅ | ❌ | ✅ | ✅ |
| Kinderspiele So | ✅ | ❌ (läuft schon live) | ✅ | ✅ |
| Crowdfunding So | ✅ | ✅ (noch nicht live-reif) | ✅ | ✅ |
| BGA Di | ✅ | ❌ | ✅ | ✅ |
| Fantasywelt Fr | ✅ | ❌ | ✅ | ✅ |
| Fantasywelt Mi | ✅ | ❌ (nur Telegram) | N/A | N/A |
| Fantasywelt Fr 2 | ✅ | ❌ (nur Telegram) | N/A | N/A |

---

## 6. Erfolgskriterien

Ein Job gilt als **„live-reif"**, wenn:
- [ ] 3 aufeinanderfolgende Läufe OHNE manuelle Korrektur
- [ ] Alle verify_article.sh-Checks bestanden
- [ ] Bild korrekt im Joomla-Frontend sichtbar
- [ ] Daniel bestätigt: „keine Korrekturen nötig"

Erst dann wird `deliver` von `local`/`origin` auf `telegram` + Joomla-Publish umgestellt.

---

## 7. Nächste Schritte (heute)

1. **Template fixen** (Schritt 1) — 5 Min
2. **verify_article.sh erstellen** (Schritt 4) — 10 Min
3. **article_server.py strippen verbessern** (Schritt 2) — 15 Min
4. **Alle Job-Prompts patchen** (Schritt 3) — 30 Min
5. **Crowdfunding-Job als Testfall** — neu laufen lassen, verify_article.sh prüfen
