218 lines
7.1 KiB
Markdown
218 lines
7.1 KiB
Markdown
# Testlauf-Protokoll
|
|
|
|
Durchgefuehrt am 20.09.2026 gegen die echten Systeme, nicht simuliert.
|
|
Alle Executions liegen in n8n und sind dort nachvollziehbar.
|
|
|
|
---
|
|
|
|
## Vorbereitung
|
|
|
|
`artikel-index.json` wurde so gesetzt, dass nur ein Artikel auf `offen` stand,
|
|
um NeuronWriter-Kontingent zu sparen:
|
|
|
|
```
|
|
brief_bereit handgeschriebene-werbebriefe
|
|
pausiert handschriftliche-mailings-kundenbindung
|
|
pausiert response-rate-direktmarketing
|
|
offen dummy-testlauf
|
|
```
|
|
|
|
---
|
|
|
|
## Lauf 1: Workflow 1, Execution 167
|
|
|
|
Start per Webhook um 10:41:00, beendet 10:43:07, Status `success`.
|
|
24 Nodes gelaufen, kein einziger Fehlerpfad.
|
|
|
|
Der Poll-Loop arbeitete wie ausgelegt:
|
|
|
|
| Node | Durchlaeufe |
|
|
|---|---|
|
|
| `Warten` | 6 |
|
|
| `Analyse abfragen` | 6 |
|
|
| `Versuch zaehlen` | 5 |
|
|
| `Poll-Limit erreicht?` | 5 |
|
|
|
|
Die Analyse war nach dem sechsten Poll fertig, also nach rund 120 Sekunden.
|
|
Von 30 erlaubten Versuchen wurden 6 gebraucht.
|
|
|
|
**Ergebnis:**
|
|
|
|
```
|
|
Briefe vorbereitet: 1, Fehler: 0
|
|
|
|
Fertig:
|
|
dummy-testlauf | Zielwortzahl 839 | 12 Pflichtbegriffe, 29 Fragen
|
|
Datei: briefe/brief-dummy-testlauf.json
|
|
Analyse: https://app.neuronwriter.com/analysis/view/ff324721305a0a60
|
|
```
|
|
|
|
**Gegenprobe im Repo:**
|
|
|
|
- `briefe/brief-dummy-testlauf.json` angelegt, 19437 Bytes
|
|
- Commit `150017a9` "Brief erzeugt: dummy-testlauf (handgeschriebene briefe roboter)"
|
|
- Commit `4c4fc0f2` "Status auf brief_bereit gesetzt (1 Artikel)"
|
|
- Zeile in `artikel-index.json` steht auf `brief_bereit`, `query_id` nachgetragen
|
|
|
|
Der Brief enthaelt alle geforderten Felder sowie den Zusatzblock:
|
|
|
|
```
|
|
query_id ff324721305a0a60 | keyword handgeschriebene briefe roboter | wortzahl_ziel 839
|
|
begriffe_pflicht 12 | begriffe_erweitert 65 | fragen 29
|
|
top-3 Fragen (nach Gewicht):
|
|
10 Wo kann ich handschriftliche Briefe schreiben lassen?
|
|
9 Wie kann ich Handschriften in digitalen Text umwandeln?
|
|
9 Wie kann ich schnell handschriftlich schreiben?
|
|
```
|
|
|
|
---
|
|
|
|
## Lauf 2a: Workflow 2, Nachbesserungspfad, Execution 168
|
|
|
|
Zielwert 72, Testartikel hatte Score 44. 24 Nodes, alle `success`.
|
|
|
|
```
|
|
Importiert: 0 | Nachbessern: 1 | Fehler: 0
|
|
|
|
Score zu niedrig, Nachbesserung liegt im Repo:
|
|
handgeschriebene-werbebriefe: Score 44 von 72
|
|
9 Pflichtbegriffe fehlen, 71 Zusatzbegriffe
|
|
Wortzahl 96 von 1178 (-1082)
|
|
Datei: nachbessern/nachbessern-handgeschriebene-werbebriefe.json
|
|
|
|
Kein Beitrag wurde veroeffentlicht. Alle Importe stehen auf Entwurf.
|
|
```
|
|
|
|
Der WordPress-Zweig wurde korrekt nicht betreten.
|
|
|
|
---
|
|
|
|
## Lauf 2b: Workflow 2, Importpfad, Execution 169
|
|
|
|
Zielwert per Webhook auf 40 abgesenkt (`{"score_ziel":40}`), damit derselbe
|
|
Artikel den Importpfad nimmt. 32 Nodes, alle `success`.
|
|
|
|
```
|
|
Importiert: 1 | Nachbessern: 0 | Fehler: 0
|
|
|
|
Als Entwurf in WordPress:
|
|
handgeschriebene-werbebriefe (Score 44, neu angelegt)
|
|
Vorschau: https://skrift.de/?p=4210&preview=true
|
|
Bearbeiten: https://skrift.de/wp-admin/post.php?post=4210&action=edit
|
|
PREISE: 2 ausgeschriebene(r) Preis(e) im Text: 2,56 EUR, 0,95 €.
|
|
Bitte durch [skrift_preis key="..."] ersetzen.
|
|
Hinweis: Cache-Endpunkt antwortete mit HTTP 403. Kein Abbruchgrund.
|
|
```
|
|
|
|
**Gegenprobe in WordPress** (`GET /wp-json/wp/v2/posts/4210?context=edit`):
|
|
|
|
```
|
|
id 4210 | status draft | slug handgeschriebene-werbebriefe
|
|
kategorien [17]
|
|
kurzantwort gesetzt
|
|
cta_ziel https://skrift.de/muster-anfordern
|
|
stand_datum 2026-09-20
|
|
_seopress_titles_title Handgeschriebene Werbebriefe: wann sie wirken
|
|
_seopress_titles_desc gesetzt
|
|
_seopress_analysis_target_kw handgeschriebene werbebriefe
|
|
faq 2 Eintraege
|
|
```
|
|
|
|
Die Kategorie `Direktmarketing` existierte nicht und wurde als ID 17 angelegt.
|
|
|
|
---
|
|
|
|
## Lauf 2c: Idempotenz, Execution 170
|
|
|
|
Derselbe Artikel ein zweites Mal, gleiche Parameter.
|
|
|
|
```
|
|
post_id 4210 | aktion: aktualisiert | alter_status: draft | status: draft
|
|
Kategorie erneut angelegt? nein (bestehende wiederverwendet)
|
|
```
|
|
|
|
`GET /wp-json/wp/v2/posts?slug=handgeschriebene-werbebriefe&status=any`
|
|
liefert genau **einen** Treffer. Es entstand kein Duplikat.
|
|
|
|
`status-importe.json` enthaelt eine Zeile, die beim zweiten Lauf ueberschrieben
|
|
statt angehaengt wurde:
|
|
|
|
```json
|
|
[{"slug":"handgeschriebene-werbebriefe","score":44,
|
|
"datum":"2026-09-20T10:47:54.336Z","post_id":4210,
|
|
"vorschau_url":"https://skrift.de/?p=4210&preview=true",
|
|
"aktion":"aktualisiert","kategorie":"Direktmarketing"}]
|
|
```
|
|
|
|
---
|
|
|
|
## Zwei Fehler, die der Testlauf gefunden hat
|
|
|
|
### 1. Webhook mit responseMode "lastNode"
|
|
|
|
Der erste Versuch endete in einem 504 von openresty, waehrend der Workflow im
|
|
Hintergrund weiterlief. Ursache: Der Webhook hielt die HTTP-Verbindung bis zum
|
|
Workflow-Ende offen, der Reverse Proxy brach nach 60 Sekunden ab.
|
|
Beide Workflows nutzen jetzt `responseMode: "onReceived"`.
|
|
|
|
### 2. body statt data bei fullResponse
|
|
|
|
n8n 1.120 liefert den Antwortkoerper bei `fullResponse: true` im Feld `data`,
|
|
nicht `body`. Alle Existenzpruefungen griffen auf `.body` zu und haetten immer
|
|
"nicht vorhanden" ergeben. Folge waere gewesen: Workflow 2 legt bei jedem Lauf
|
|
einen neuen Beitrag an, statt den bestehenden zu aktualisieren.
|
|
An sieben Stellen korrigiert und versionsfest gemacht:
|
|
|
|
```js
|
|
const K = (r) => (r && r.body !== undefined) ? r.body : ((r || {}).data);
|
|
```
|
|
|
|
Lauf 2c belegt, dass die Idempotenz jetzt haelt.
|
|
|
|
---
|
|
|
|
## Netzwerkbefund: Gitea war aus n8n nicht erreichbar
|
|
|
|
Der erste Lauf scheiterte mit `timeout of 60000ms exceeded` beim Lesen der
|
|
Artikeltabelle. Die Diagnose aus n8n heraus ergab:
|
|
|
|
| Ziel | Ergebnis |
|
|
|---|---|
|
|
| `https://gitea.lucas-orth.de/api/v1/version` | `ECONNABORTED` |
|
|
| `http://gitea.lucas-orth.de/api/v1/version` | HTTP 301, Server openresty |
|
|
| `https://app.neuronwriter.com/...` | HTTP 401 (erreichbar) |
|
|
| `https://skrift.de/wp-json/` | HTTP 200 |
|
|
| `http://gitea:3000/api/v1/version` | **HTTP 200** |
|
|
|
|
`gitea.lucas-orth.de` loest auf `100.98.99.19` auf, eine NetBird-Overlay-Adresse.
|
|
Der n8n-Host erreichte den dortigen openresty auf Port 80, aber nicht auf 443.
|
|
|
|
Geloest ueber das Docker-Netz: beide Workflows sprechen Gitea jetzt als
|
|
`http://gitea:3000` an. Der Weg laeuft nicht ueber den Reverse Proxy und
|
|
nicht ueber das Overlay, ist damit schneller und faellt nicht aus, wenn am
|
|
Proxy etwas geaendert wird.
|
|
|
|
Zum Nachtesten liegt der Hilfsworkflow `netzcheck` in n8n:
|
|
|
|
```bash
|
|
curl -X POST https://n8n.lucas-orth.de/webhook/probe \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"url":"http://gitea:3000/api/v1/version"}'
|
|
```
|
|
|
|
---
|
|
|
|
## Offene Punkte nach dem Testlauf
|
|
|
|
**Cache leeren gibt HTTP 403.** Der Benutzer `ai-agent` hat als Redakteur nicht
|
|
die Berechtigung fuer `POST /wp-json/seopress/v1/commands/clear-cache`.
|
|
Der Workflow behandelt das als Hinweis, nicht als Fehler. Bei Entwuerfen ist ein
|
|
Cache-Purge ohnehin wirkungslos. Relevant wird es erst, wenn ein bereits
|
|
veroeffentlichter Beitrag aktualisiert wird. Wer das braucht, gibt der Rolle
|
|
Redakteur die noetige Capability oder leert nach dem Veroeffentlichen von Hand.
|
|
|
|
**Testreste.** In WordPress steht Beitrag 4210 als Entwurf, dazu die Kategorie
|
|
`Direktmarketing` (ID 17). In NeuronWriter liegen zwei Analysen
|
|
(`565abcca58f65e52`, `ff324721305a0a60`) mit je einer importierten Revision.
|
|
Beides kann bleiben oder geloescht werden.
|