<!-- AUTO-GENERATED by scripts/wi-claude-rules-sync.sh — do not edit. -->
<!-- bundle: 60-smoke-matrix | sources: 4 .mdc files -->
---
name: smoke
description: WI 5-host journey smoke, mail smoke, AI webinar matrix
---

<!-- source: .cursor/rules/wi-modern-room-journey-smoke-default.mdc -->

# WI — Modern Room Journey Smoke (Default)

**Kanon ab 2026-07-05 (Tobias):** Nach URL-/Routing-Fixes (Modern Room, Master-Switch, Mail-Join) ist dieser Smoke der **Default-Follow-up** und gilt **parallel** zu Release-Smoke und AI-Matrix. Nicht optional, wenn Journey/Mail/Preview/Redirect berührt wurde.

Cross-Ref: [`wi-modern-room-canonical.mdc`](wi-modern-room-canonical.mdc), [`wi-ai-webinar-smoke-scope.mdc`](wi-ai-webinar-smoke-scope.mdc), [`wi-multiserver-mail-smoke.mdc`](wi-multiserver-mail-smoke.mdc), [`wi-real-registration-smoke-before-user-test.mdc`](wi-real-registration-smoke-before-user-test.mdc).

## Ziel

Pro **Server-Typ** (5-Host-Matrix) und pro **Webinar-Typ** (mindestens GB Evergreen + HC Live auf Cloudways; ideal alle vier: GB/HC × Live/Evergreen) die **volle Teilnehmer-Kette** plus **Admin-Preview** plus **Mail-Join-URL** verifizieren.

| Phase | Surface | Erwartung (Modern Room Default) |
|-------|---------|----------------------------------|
| **J1 Reg** | Reg-Formular sichtbar | Submit → TY (frische `lid`, MX-Mail) |
| **J2 TY** | Countdown / Bestätigung | Kein Reg-Formular; gültige `lid` |
| **J3 Live** | Modern Room | Reg-**Basis-URL** + `live&webinar&lid`; `#webinarContent` / Player; **kein** „Register now“ |
| **J4 Replay** | Replay-Modus | `?replay&webinar&lid` auf Raum-Basis |
| **J5 Ended** | Closed / Beendet | Master-Switch `closed` oder Ended-URL; kein Live-Player als Reg |
| **A1 Admin-Preview** | tab2 „Webinar Page“ | Eingeloggt: `lid=11111&preview=true` → **immer** Raum |
| **M1 Mail-Join** | `wi_url_live_join` / `{WEBINARURL}` live | Reg-Basis + `live&webinar&lid`; Switch entscheidet TY vs Raum |
| **V1 Version** | Remote = local | `WEBINARIGNITION_VERSION` auf jedem Host |

## 5-Host-Matrix (Pflicht)

Dieselben Ziele wie [`wi-ai-webinar-smoke-scope.mdc`](wi-ai-webinar-smoke-scope.mdc):

| # | Server-Typ | Label | Env / Zugang |
|---|------------|-------|--------------|
| 1 | WordPress.com / Nginx | WI.com Staging | `.env.wicom-staging.local` |
| 2 | Cloudways Nginx-Apache | Cloudways Staging | `.env.cloudways-staging.local`, `scripts/env/staging-wp-browser.local.env` |
| 3 | Microsoft IIS | IIS Test | `.cursor/wi-site-file-change-notes.md` |
| 4 | OpenLiteSpeed | LightNode VPS | `.env.lightnode-ols-wp.*.local` |
| 5 | Apache | Apache Test | `.cursor/wi-site-file-change-notes.md` |

Host ohne Zugang = **NEEDS DETAILS**, nicht grün. Andere vier Hosts **parallel** weiterlaufen (nicht warten bis Host 1 fertig).

## Parallelität (Pflicht ab 2026-07-07)

Matrix-Journey = **5 Hosts parallel**, **gestaffelter Start** (wenig Grün + langsam zuerst, Cloudways zuletzt). Kanon: [wi-multiserver-mail-smoke.mdc](wi-multiserver-mail-smoke.mdc) § Parallelität, Strategien A/B/C, Run-Log-Reihenfolge.

- **Ebene A (curl/redirect):** [`wi-multiserver-redirect-smoke.sh`](../scripts/wi-multiserver-redirect-smoke.sh) pro Host; Apache ggf. Playwright (Bot-Wall).
- **Ebene B (Browser):** eigene Playwright-Session **pro Host**.
- **MAIL-V / Full-Mail:** `WI_MAIL_SMOKE_FILTER=<label>` — Startreihenfolge aus [`SMOKE-RUN-LOG.md`](../../wi-dev/local/reports/SMOKE-RUN-LOG.md).

**Strategie B/C pro Host:** `parallel_ok=yes` → Mail + Journey gleichzeitig mit **getrennten `cid`s**. `parallel_ok=no` (Apache) → **C** sequentiell, im Run-Log markieren. Nie zwei Worker auf demselben Host ohne B.

## Zwei Ebenen (beide nötig für „grün“)

### Ebene A — Curl/Redirect (schnell, alle Hosts)

Runner: [`scripts/wi-multiserver-redirect-smoke.sh`](../scripts/wi-multiserver-redirect-smoke.sh)

Pro Target: **Reg** → **TY confirmed** (kein Redirect-Loop) → **Live join** (finale URL behält `live`) → **Replay** → optional **Ended/closed** URL.

Env: `scripts/env/wi-multiserver-targets.local.env` (Vorlage: [`wi-modern-room-journey-smoke.local.env.example`](../scripts/env/wi-modern-room-journey-smoke.local.env.example)).

### Ebene B — Real Browser (Pflicht vor User-Test)

1. **Anonym/Inkognito:** echte Reg → Submit → TY-Screenshot; Mail-Join-Link aus IMAP/Log öffnen → Live-Screenshot.
2. **Eingeloggt (Admin):** tab1/tab2 Preview-Link folgen **in derselben Session** (kein neuer Gast-Kontext). Siehe [`wi-screenshot-hygiene.mdc`](wi-screenshot-hygiene.mdc) Sinn-Check.

Playwright-Helfer (lokal): `wi-dev/local/wi-p48-evergreen-room-smoke.mjs`, `wi-dev/local/wi-p48-cloudways-hc-room-smoke.mjs`.

Screenshots: `.cursor-wi-screenshots/ss-journey-<host>-<phase>.png`.

## Mail (zusätzlich, fest)

[`wi-multiserver-mail-smoke.mdc`](wi-multiserver-mail-smoke.mdc): MAIL-V + MAIL-C + MAIL-R1…R5 (Smoke-Offsets, 5-Min-Live-Dauer auf Sandbox-Hosts).

## Default-Orchestrator

```bash
./scripts/wi-modern-room-journey-smoke-default.sh          # Ebene A alle konfigurierten Hosts
./scripts/wi-modern-room-journey-smoke-default.sh version  # nur MAIL-V / Version
./scripts/wi-modern-room-journey-smoke-default.sh full     # A + Mail version (B manuell/Playwright)
```

Report: `scripts/reports/wi-modern-room-journey-smoke.txt`.

## Abnahme pro Host

Host **journey-grün** nur wenn:

- V1 Version match
- J1–J3 grün (Reg submit + TY + Live Room Shell)
- J4 Replay HTTP/body ok
- J5 Ended ok oder dokumentiert „Host ohne Test-Kampagne closed“
- A1 Admin-Preview Raum (eingeloggt)
- M1 Mail-Join URL-Pattern = Reg-Basis + live params (wp eval oder Mail-Body)
- Ebene B Screenshots für mindestens J1+J3+A1 auf dem Host

## Wann auslösen (Agent)

- Nach **#A950**-Klass Fixes (Modern Room, Preview, Mail-Join, Skip-TY)
- Vor **`working ✓`** wenn Journey/Routing/Mail/Preview im Diff
- Vor **Freemius / wp.org** Release (zusammen mit [`wi-pre-release-smoketest.mdc`](wi-pre-release-smoketest.mdc))
- Nach Deploy auf **beliebigen** Matrix-Host

## Follow-up P48 / #A950 (Stand 2026-07-05)

Partial erledigt: Admin-Preview + URL-Resolver auf WI.com id=76 + Cloudways id=8 (**4.14.15**). **Volle Matrix J1–J5 auf allen 5 Servern** = nächster Lauf via Orchestrator oben.

---

<!-- source: .cursor/rules/wi-multiserver-mail-smoke.mdc -->

# WI — Multi-Server Mail Smoke (fest)

Ohne funktionierende **Confirmation** und **automatische Reminder** (Cron/Action Scheduler, nicht Sofort-Mail) kommen fast keine Teilnehmer ins Live-Webinar. Dieser Smoke ist deshalb **Pflicht** neben Reg → TY → Raum.

Matrix = dieselben fünf Server wie [wi-ai-webinar-smoke-scope.mdc](wi-ai-webinar-smoke-scope.mdc). Runbook: [`.cursor/wi-site-file-change-notes.md`](../wi-site-file-change-notes.md) Abschnitt *Multi-Server Mail Smoke*.

Registry: `MAIL-MULTI` · `timing_profile: mail-6min` · Dashboard: [`plans/SMOKE-DASHBOARD.md`](../../plans/SMOKE-DASHBOARD.md).

## Pflicht vor jedem Lauf

1. **Versions-Check (hart):** Remote `?ver=` auf öffentlicher WI-Seite = lokales `webinarignition.php` — **Ausnahme Apache/Byethost:** curl trifft Bot-Wall (`__test`-Cookie / `aes.js`) → **`version_via=ftp`** in Env: `Version:` aus `webinarignition.php` per **FTP** `ftpupload.net:21` (`.env.apache.local`). **Kein SSH** auf Byethost — Full-Mail: **`ssh_prefix=wp-admin`** → Playwright + `wi-staging-mail-probe.php?run_cron=1`. Campaign-ID: [wp-admin Webinars](https://wi-on-apache.byethost7.com/wp/wp-admin/admin.php?page=webinarignition-dashboard) → Edit hover `&id=N` (Live **14**, Evergreen 13). Spalte 8: `curl` | `ftp` | `ftp-fallback`.
2. **Deploy:** Gleiche Plugin-Version auf allen Matrix-Hosts (ZIP/SFTP), dann erneut Version prüfen.
3. **Smoke-Offsets (QA):** **MAIL-6MIN** auf Smoke-Hosts — **2m / 1m / at live / 1m / 1d**, Dauer **1 Min** (siehe [`wi-smoke-test-webinar-timing.mdc`](wi-smoke-test-webinar-timing.mdc)). Tab8 **Arm timing sandbox**. **Keine** Mail-Time-Compression.
4. **Host-Isolation:** Ein Host fail stoppt nie die anderen — sofort melden, weiter testen (3/5 grün = OK Zwischenstand).

## Parallelität, Host-Isolation und Start-Reihenfolge (Pflicht ab 2026-07-07)

**Matrix = 5 Hosts parallel**, aber **gestaffelter Start** (siehe Reihenfolge unten), nicht blind „Cloudways zuerst“. Ziel: schwächster/langsamster Host hat die meiste Laufzeit; schnellster/grünster Host startet zuletzt, damit alle **relativ gleichzeitig** fertig sind.

### Parallel starten (Agent)

| Methode | Wann |
|---------|------|
| **5× Cursor-Subagents** (Multitask) | Full-Mail, Journey Ebene B, Upload-Smoke — je Host ein Worker, Start nach Reihenfolge |
| **5× Shell-Background** | `WI_MAIL_SMOKE_FILTER=<label> ./scripts/wi-multiserver-mail-smoke.sh full &` — **nicht** alle auf einmal feuern wenn Stagger gewünscht |
| **Version-Matrix parallel** | `./scripts/wi-multiserver-mail-smoke.sh version` ist schnell; Reihenfolge egal |

**Verboten bei Parallel-Lauf:**

- **Eine** Playwright-Session über mehrere Hosts teilen — pro Host eigener Browser-Kontext / eigene Env-Datei
- Poll-Intervalle **global** verkürzen — **pro Host** Env-Werte beibehalten
- Apache/Byethost: kein paralleles HTTP-Hammern gegen **dieselbe** Origin
- **Zwei aktive Smoke-Läufe auf demselben Host** ohne Strategie B (getrennte `cid`) — siehe unten
- **Cloudways immer zuerst** starten — veraltet; siehe Start-Reihenfolge

### Drei Strategien (Kanon)

| Strategie | Wann | Regel |
|-----------|------|--------|
| **A — Ein Test / Host** | Default: ein Smoke-Typ aktiv | `WI_MAIL_SMOKE_FILTER=<label>` · ein Subagent pro Host · vor Start prüfen ob Host schon läuft |
| **B — Gleichzeitig, getrennte Webinare** | Host **kann** Mail + Journey parallel | **MAIL-6MIN:** eigene Live-`cid` (Sandbox arm). **Journey:** andere `cid`/Evergreen — **nie** dieselbe `cid**. In Run-Log: `parallel_ok=yes` |
| **C — Sequentiell auf einem Host** | Host **kann nicht** parallel (Cron, Bot-Wall, Playwright-only) | Erst Mail grün, **dann** Journey auf demselben Host. In Run-Log: `parallel_ok=no` + Grund. **Nicht** B erzwingen |

**Agent:** Vor Matrix-Lauf pro Host in [`SMOKE-RUN-LOG.md`](../../wi-dev/local/reports/SMOKE-RUN-LOG.md) § Host-Registry prüfen/setzen: `parallel_ok` yes/no. Apache/Byethost typisch **C** (`parallel_ok=no`). SSH-Hosts (Cloudways, WI.com, IIS, LiteSpeed) default **B möglich**, solange getrennte `cid`s.

### Start-Reihenfolge (gestaffelt, Pflicht)

**Vor jedem Matrix-Lauf** Reihenfolge aus Run-Log § **Nächste Start-Reihenfolge** lesen. **Nach jedem Lauf** neu sortieren und eintragen.

**Sortierung (beide Faktoren):**

1. **Wenigstes Grün zuerst** — offene Phasen, letzter FAIL, nie Full-Mail grün → früher starten
2. **Langsamster zuerst** — Playwright-only, langsamer Cron, Bot-Wall, längere Polls → früher starten (Apache typisch #1)

**Start-Regel:**

- **Erster Start** = Host mit schlechtestem Score (wenig Grün + langsam)
- **Letzter Start** = Host mit meistem Grün + schnellstem Transport (Cloudways typisch **zuletzt**, nicht zuerst)
- Zwischenhosts nach Score absteigend
- Optional kurze Verzögerung zwischen Starts (z. B. 30–60s), damit Enden zusammenfallen — nicht alle 5 auf `T+0`

**Aktualisierung (Pflicht nach Lauf):** In Run-Log Tabelle `green_score`, `speed`, `parallel_ok`, `next_start_rank` pro Host pflegen.

### Run-Log nach jedem Matrix-Lauf (Pflicht)

Nach jedem Mail-/Journey-/Free-Matrix-Lauf in [`wi-dev/local/reports/SMOKE-RUN-LOG.md`](../../wi-dev/local/reports/SMOKE-RUN-LOG.md):

1. **Gut gelaufen** — Host/Phase, Version
2. **Nächster Run** — offene Hosts, `cid`s, nur R4 vs Full-Mail
3. **Nächstes Mal besser** — Lessons
4. **Host-Registry + Nächste Start-Reihenfolge** — `parallel_ok`, Grün-Score, Speed-Rank, sortierte Startliste für **nächsten** Run

Kurzfassung im Chat wenn Matrix im Task war.

### Getunte Env-Werte (Repo-Kanon)

Quelle: [`scripts/env/wi-multiserver-mail-smoke.local.env.example`](../scripts/env/wi-multiserver-mail-smoke.local.env.example) · Runner: [`scripts/wi-multiserver-mail-smoke.sh`](../scripts/wi-multiserver-mail-smoke.sh) (Python-Block ~Zeile 341)

| Variable | Default | Zweck |
|----------|---------|--------|
| `WI_MAIL_SMOKE_POLL_SEC` | **45** | IMAP + Cron-Poll zwischen MAIL-6MIN-Schleifen (Cloudways-Default 30–45s ok) |
| `WI_MAIL_SMOKE_POLL_SEC_SLOT4` | **10** | Nach Slot 3 `sent`: schnelleres Poll für Slot 4 (Ende-Reminder) |
| `WI_MAIL_SMOKE_MAX_LOOPS` | **50** (Apache **70**) | Timeout — Apache: ~15 min sandbox lead + Slot-4-Kette |
| `WI_MAIL_SMOKE_EXPECT_VERSION` | leer = lokal | Apache: oft **`4.15.29`** (FTP-Remote ≠ lokaler Patch-Stand) |
| `WI_MAIL_SMOKE_FILTER` | leer | Nur ein Host: `cloudways` \| `wicom` \| `iis` \| `litespeed` \| `apache` |
| `WI_MAIL_IMAP_ENV` | catch-all | **Ein** Postfach für alle Hosts (`@wp2leads.com`) — kein per-Server-IMAP |

**Freemius-Wartelogik** (Upload-Smoke, nicht Mail-Runner): API-Poll **60s**; kein zweiter POST **&lt; 5 Min** (`FREEMIUS_MIN_WAIT_BEFORE_RETRY_SEC=300`); siehe [`.cursor/wi-current-ideas.md`](../wi-current-ideas.md) Eintrag 2026-07-07 Free-Test.

### Pro Host: Transport, Speed, Besonderheiten

| Host | Version (MAIL-V) | Cron / Full-Mail | Rate / Vorsicht |
|------|------------------|------------------|-----------------|
| **Cloudways** | `curl` `?ver=` | SSH `wp eval` + AS/cron | Standard-Poll **45s**; kanonischer Cursor-QA-Host |
| **WI.com** | `curl` | SSH `wp eval` | Bei Flaky-Site Poll **45–60s** (`WI_MAIL_SMOKE_POLL_SEC=60`), nicht aggressiver SSH |
| **IIS** | `curl` | SSH `wp eval` | Wie Cloudways; SFTP/wp-admin Upload getrennt vom Mail-Lauf |
| **LiteSpeed** | `curl` | SSH `wp eval --allow-root` | `--allow-root` Pflicht; sonst gleiche Polls |
| **Apache / Byethost** | **FTP** `ftpupload.net:21` (`version_via=ftp`) — **kein curl HTML** (Bot-Wall `__test`/`aes.js`) | **wp-admin** + Playwright + `wi-staging-mail-probe.php?run_cron=1` + AS (5×) — **kein SSH** | Poll **15s**, **70** Loops, `WI_MAIL_SMOKE_EXPECT_VERSION=4.15.29`; Live **cid=14**; Slot-4 (Replay) braucht volles Fenster — Grace 5m |

Apache-Zeile in Targets: `ssh_prefix=wp-admin` · `version_via=ftp` · `.env.apache.local` · Runner [`scripts/lib/wi-apache-mail-remote.mjs`](../scripts/lib/wi-apache-mail-remote.mjs).

### Agent-Pflicht (formalisiert)

1. Matrix-Smoke = **5 Worker**, Start **gestaffelt** nach Run-Log-Reihenfolge (schwächster/langsamster zuerst, Cloudways zuletzt).
2. Report pro Host isoliert; ein FAIL blockiert andere **nicht**.
3. Nach Lauf: Summary + **Host-Registry/Reihenfolge** in Run-Log aktualisieren — [`scripts/reports/wi-multiserver-mail-smoke.txt`](../scripts/reports/wi-multiserver-mail-smoke.txt).

Cross-Ref Parallel-Matrix gesamt: [wi-ai-webinar-smoke-scope.mdc](wi-ai-webinar-smoke-scope.mdc), [wi-modern-room-journey-smoke-default.mdc](wi-modern-room-journey-smoke-default.mdc).

## E-Mail-Smoke-Zeitachse MAIL-6MIN (Live-Start = T)

| Phase | Zeitpunkt | Prod-Semantik | Mail-ID |
|-------|-----------|---------------|---------|
| Vor Live | T − 2m | Tag vorher | MAIL-R1 |
| Vor Live | T − 1m | Stunde vorher | MAIL-R2 |
| Bei Live | T | Bei Live | MAIL-R3 |
| Live-Ende | T + 1m | 1 Min Dauer | — |
| Nach Ende | T + 2m | 1 Std danach → 1 Min | MAIL-R4 |
| Nach Ende | T + 1d | 1 Tag danach | MAIL-R5 (Folgetag) |

**Kette R1→R4 ≈ 4 Min** Reminder-Fenster + MAIL-C vorher. Gesamt-Session ~6 Min inkl. Cron-Polls.

## Pflicht-Mails (Live-Kampagne, GB)

| ID | Mail | Auslöser | Nachweis |
|----|------|----------|----------|
| MAIL-V | Plugin-Version | Asset `?ver=` oder wp-admin Plugins | Remote = local |
| MAIL-C | Confirmation / Signup | Reg Submit (sofort) | IMAP / Mail-Log |
| MAIL-R1 | 2 Min vorher (Slot 1) | **Cron/AS** | tab8 Log + Offset |
| MAIL-R2 | 1 Min vorher (Slot 2) | **Cron/AS** | tab8 Log + Offset |
| MAIL-R3 | Bei Live (Slot 3) | **Cron/AS** at live | at live start |
| MAIL-R4 | 1 Min nach Ende (Slot 4) | **Cron/AS** | 1m after live **end** |
| MAIL-R5 | 1 Tag nach Ende (Slot 5) | **Cron/AS** | separater Pass / partial OK |

**Wichtig:** MAIL-C ist Sofort-Versand. **MAIL-R1–R5** müssen über den **automatischen** Reminder-Prozess laufen — nicht als direkter Folge-Job der Registrierung.

## Nachweis pro Host

**IMAP (hart — Tobias 2026-07-07):** **`@wp2leads.com` ist Catch-All.** Jede Registrierung mit `*@wp2leads.com` auf **jedem** Matrix-Host landet im **gleichen** Postfach. Es gibt **kein** per-Server-IMAP — eine Datei für alle:

- **Kanon:** [`scripts/env/wi-mail-imap-catchall.local.env`](../scripts/env/wi-mail-imap-catchall.local.env) (kopieren von [`wi-mail-imap-catchall.local.env.example`](../scripts/env/wi-mail-imap-catchall.local.env.example))
- **Legacy-Fallback:** Repo-Root `.env.p22-mail-webhook.local` (gleiche Keys `WI_P22_IMAP_*`)
- **Login:** z. B. `catch@saleswonder.biz` auf `s14w11.meinserver.io` — empfängt **alle** `@wp2leads.com`-Adressen
- **Env-Zeile pro Host:** `mail_proof=imap` (immer). Blocker für Full-Mail: fehlendes **campaign_id** oder (non-Apache) **SSH**. **Apache:** `ssh_prefix=wp-admin`, kein SSH — nur **FTP `ftpupload.net`** + wp-admin/Playwright.
- **Groundhogg (nur WI.com Staging, optional):** loggt Mails lokal in wp-admin — **kein** Matrix-Nachweis. CW/IIS/LiteSpeed/Apache: **nur** shared IMAP `@wp2leads.com`. `mail_proof=groundhogg` im Runner ist deprecated → `imap`.

Report: `scripts/reports/wi-multiserver-mail-smoke.txt` + optional `.cursor-wi-screenshots/wi-multiserver-mail-smoke.json`.

## Runner

```bash
cp scripts/env/wi-mail-imap-catchall.local.env.example scripts/env/wi-mail-imap-catchall.local.env
# oder: ln -sf ../../.env.p22-mail-webhook.local scripts/env/wi-mail-imap-catchall.local.env
cp scripts/env/wi-multiserver-mail-smoke.local.env.example scripts/env/wi-multiserver-mail-smoke.local.env
./scripts/wi-multiserver-mail-smoke.sh version          # nur Versions-Matrix
./scripts/wi-multiserver-mail-smoke.sh full             # Version + Mail (MAIL-6MIN)
```

Nach Lauf: `node scripts/wi-smoke-dashboard-refresh.mjs`

## Abnahme Matrix

Host ist **mail-grün (Fast-Gate)** wenn: MAIL-V + MAIL-C + MAIL-R1 + MAIL-R2 + MAIL-R3 + **MAIL-R4** grün. **MAIL-R5** grün am Folgetag oder dokumentiert `partial`. Ein Host ohne Version-Match = **FAIL** auf diesem Host nur — andere Hosts weiter.

Cross-Ref: [wi-pre-release-smoketest.mdc](wi-pre-release-smoketest.mdc), [wi-autonomous-multiserver-upload-test.mdc](wi-autonomous-multiserver-upload-test.mdc), [wi-real-registration-smoke-before-user-test.mdc](wi-real-registration-smoke-before-user-test.mdc).

## Smoke-Dashboard (Pflicht-Abschluss, Tobias 2026-07-07)

**Jede** Agent-Antwort nach Mail-/Journey-/Upload-/Free-Matrix endet mit diesem Block (unten im Chat).

**Host-Label (hart):** **`WI.com Staging`** (`staging-9959-tobiasbconrad.wpcomstaging.com`). **Nie** „WI.com“ allein (Live = webinarignition.com).

### Smoke-Reihenfolge (hart — Tobias)

1. **Release-Kandidat** festlegen (z. B. `4.15.65`).
2. **UPLOAD-ZIP** (volle Premium-ZIP, wp-admin Replace) auf **jedem** Matrix-Host für **diesen** Kandidaten — `wi-upload-smoke-matrix.mjs`.
3. Erst wenn Upload-ZIP für Kandidat **grün oder bewusst dokumentiert gelb** → **Version** (MAIL-V) muss Kandidat zeigen.
4. Dann **Full-Mail / Journey** (Premium). **Kein** Mail-/Journey-Smoke auf Teile-Deploy/Flickwerk als Release-Gate werten.

**Fixen:** SFTP/FTP/Einzeldatei ok. **Smoke/Release-Gate:** immer **ganzes Plugin als ZIP**.

### Version vs Upload-ZIP

| Spalte | Prüfung | 🟢 grün | 🟡 gelb | 🔴 rot |
|--------|---------|---------|---------|--------|
| **Version** | Remote `?ver=` / FTP `Version:` | **Zahl = Release-Kandidat** (z. B. `🟢 4.15.65`) | Zahl sichtbar, **≠ Kandidat** (`🟡 4.14.76`) | fehlt / Bot-Wall |
| **Upload-ZIP** | Letzter **wp-admin ZIP Replace** (Premium) | **Letzter ZIP = Kandidat** (`🟢 ZIP 4.15.65`) | **Letzter ZIP älter** (`🟡 last ZIP 4.14.76`) — **nie grün bei alter ZIP** | ZIP-Fail / Fatal / nie getestet |

**Version-Spalte:** immer **Versionsnummer** anzeigen, nicht nur Farbe.

**Upload-Spalte:** **nicht** „kein ZIP 4.15.29“ — immer **letzten belegten ZIP-Stand** nennen: `last ZIP 4.14.76` oder `last ZIP — (nur FTP/SCP 4.15.12)`.

**Teildeploy:** Version kann Kandidat zeigen, Upload-ZIP bleibt **gelb** bis wp-admin-ZIP für Kandidat grün.

### Free vs Premium (Matrix)

Pro Host nur **ein** WI-Slug aktiv (`webinarignition-premium` **oder** `webinar-ignition`). Dual-Slug = Journey 🟡 + Hinweis.

**Zwei Blöcke in der Tabelle:**

**Premium (Paid):**

| Host | Aktiver Slug | Version | Upload-ZIP | Full-Mail | Journey |

**Free (optional pro Host / global Leak):**

| Host | Free Upload-ZIP | Free Journey | Hinweis |

Global: **Free leak** (Freemius-Free-ZIP grep, eine Zeile, nicht pro Host).

**Mail/Journey ohne ZIP-Gate:** Zelle `—` oder 🟡 + „blockiert: Upload-ZIP ≠ Kandidat“.

Unter der Tabelle: **Details (gelb/rot)** — Ursache + Empfehlung je Zelle.

**Pflicht:** Zusammenfassung · Release-Empfehlung · Nächster Schritt.

Quelle: [`SMOKE-DASHBOARD.md`](../../wi-dev/local/reports/SMOKE-DASHBOARD.md), Registry `wi-release-smoke-registry.yaml`.

## MAIL-6MIN Evergreen (Host-Test, kanonisch ab 2026-07-06)

**Kampagne CW:** id **139** · Reg [`/wi-ml-smoke-hindi/`](https://wordpress-1301098-5039235.cloudwaysapps.com/wi-ml-smoke-hindi/) · Admin Tab Zeiten [`id=139&wi_editor=1`](https://wordpress-1301098-5039235.cloudwaysapps.com/wp-admin/admin.php?page=webinarignition-dashboard&id=139&wi_editor=1)

**Ablauf (Agent autonom — kein User-Klick):**

1. **Instant aus:** `auto_today = no` (sonst kein klares Slot-Picking auf Reg).
2. **Eine Slot-Zeit** (`auto_time_1`) auf **jetzt + 8 Min** (Panama/`auto_timezone_custom`), alle Wochentage `yes`, speichern.
3. **MAIL-6MIN-Offsets:** `wi_webinar_sandbox_apply_short_offsets()` + `auto_video_length = 1`.
4. **Leads trimmen:** nur 0–1 Test-Lead in `webinarignition_leads_evergreen` für diese Kampagne.
5. **Registrieren** via `webinarignition_add_lead_auto` mit `date` + `time` des Slots.
6. **Cron/AS** pollen · IMAP `@wp2leads.com` · Lead-Spalten `date_*_check` = `sent`.

**Skip-Regel (hart, ab 4.15):** Kein Same-Day-/Same-Hour-Skip mehr. Skip **nur** wenn `Registrierungszeit > Slot-Sendezeit + Grace` (`wi_mail_notif_eg_lead_check_columns_at_registration`). Offset „2 Min vorher“ + Reg 10 Min vorher → **send**. Reg 1 Min vor Live, Slot bei 3 Min vorher → **skip**.

**Fallback UI:** Vorhandene Zeit im Editor ändern (Slot → +4 Min) statt neuer Slot — wenn Multi-Slot-Dropdown zu komplex, **Instant-Webinare aus** und nur `auto_time_1` nutzen.

---

<!-- source: .cursor/rules/wi-ai-webinar-smoke-scope.mdc -->

# WI — AI Webinar Smoke Scope

For AI webinar import/registration-page smoke tests, use only this approved five-host matrix unless Tobias explicitly expands it:

- webinarignition.com staging — WordPress.com/Atomic, treat as Nginx-style hosting.
- Cloudways Staging (Cursor test) — Cloudways/Nginx-Apache mix, canonical Cursor QA target.
- Microsoft/IIS server — Windows/IIS compatibility target.
- LiteSpeed / OpenLiteSpeed — LightNode VPS (`litespeed-lightnode.webinarignition.com`), see `.env.lightnode-ols-wp.local.example`.
- Apache server — classic Apache compatibility target.

Do not touch customer sites or customer production data (for example Felix, Santegra, WP2Leads customer sites) without explicit approval in the current chat.

Campfire is excluded from autonomous smoke runs when access is unavailable; public read-only checks are okay.

On approved staging/test hosts, the agent may publish AI-generated test campaigns/pages when needed to complete public anonymous Reg -> Submit -> TY/live smoke tests. This includes changing a newly created AI campaign from draft/unpublished/test state to published/Go, as long as the action stays on the named test server and serves the current QA goal.

Goal: WebinarIgnition must run correctly on all approved server types through global fixes that follow WordPress standards. Prefer WordPress APIs and portable behavior over server-specific branches. The matrix exists to prove the same WI code works on WordPress.com/Nginx, Cloudways, IIS, LiteSpeed/OpenLiteSpeed, and Apache.

If a target URL, wp-admin login, upload method, or env file is unclear, stop before marking that target green and ask Tobias for the missing detail so it can be solved immediately:

- A: provide/update the target URL plus local env/access note for that exact host.
- B: mark the host as temporarily blocked and continue the other four hosts.
- C: replace that host in the approved matrix with a new named test host.

For each target, the minimum smoke evidence is: plugin version verified, new AI Live webinar, new AI Evergreen/Auto webinar, new AI Fixed-date webinar, public registration page shows no visible `nnnn` / JSON / shortcode leak, registration form visible after publish, real submit to Thank-You where the site allows it, and screenshot(s) saved locally.

**Mail smoke (fest, seit 2026-07-02):** Zusätzlich Pflicht gemäss [wi-multiserver-mail-smoke.mdc](wi-multiserver-mail-smoke.mdc) — Versions-Check + Confirmation-Mail + automatische Reminder Slot 1 (1 Tag vorher) und Slot 2 (1 Stunde vorher) via Cron/AS. Runner: `./scripts/wi-multiserver-mail-smoke.sh`.

**Matrix-Parallelität (Pflicht ab 2026-07-07):** 5 Hosts parallel (Multitask / Filter), **gestaffelter Start**: wenig Grün + langsam zuerst (Apache), Cloudways zuletzt — Reihenfolge aus [`SMOKE-RUN-LOG.md`](../../wi-dev/local/reports/SMOKE-RUN-LOG.md). B/C: `parallel_ok=yes` → getrennte Webinare; `parallel_ok=no` → sequentiell. Details: [wi-multiserver-mail-smoke.mdc](wi-multiserver-mail-smoke.mdc).

**Journey smoke (Default ab 2026-07-05):** Volle Kette Reg → TY → Live (Modern Room) → Replay → Ended + Admin-Preview + Mail-Join auf **allen 5 Server-Typen**. Rule: [wi-modern-room-journey-smoke-default.mdc](wi-modern-room-journey-smoke-default.mdc). Runner: `./scripts/wi-modern-room-journey-smoke-default.sh`.

**Upload smoke (Pflicht vor Release, seit 2026-07-06):** wp-admin ZIP install/replace pro Matrix-Host (Compat: IIS/Apache/LiteSpeed/WP.com/Cloudways). Registry: [wi-pre-release-smoketest.mdc](wi-pre-release-smoketest.mdc) § Release Smoke Registry · `scripts/reports/wi-release-smoke-registry.yaml` · Runner: `node wi-dev/local/wi-upload-smoke-matrix.mjs`.

All required AI webinar types must work on every approved server type. Do not treat "unsupported here" as an acceptable green result. If a type fails because of license, missing UI, setup, server behavior, upload, or routing, mark it `NEEDS DETAILS` or `FAIL` with the exact missing detail or defect, ask Tobias for the needed access/setup immediately, and keep the host not green until the issue is resolved and retested.

Red / `FAIL` / `NEEDS DETAILS` is never a final answer for this matrix. It only means "not green yet": continue diagnosing, try the next safe upload/login/test path, and give Tobias concrete options or exact actions needed. Stop only when the host is green, a user-owned action is required (for example SSO/CAPTCHA/hosting outage), or Tobias explicitly pauses the run.

## Current Target Registry

Keep this registry current when Tobias adds or changes a smoke host. Do not paste secrets here.

Access and upload details are source-of-truth outside this rule:

- Non-secret runbooks/site notes: `.cursor/wi-site-file-change-notes.md`
- Local access/env index: `STAGING-ACCESS.local.md`, `WEBINARIGNITION-COM-ACCESS.local.md`, `WI-ENV-INDEX.local.md`
- Host-specific env files named in those notes, for example `.env.cloudways-staging.local`, `.env.wicom-staging.local`, `.env.lightnode-ols-wp.38-54-84-124.local`, `.env.webinarignition-live.local`

When adding a new smoke host, first find or create/update the central access/site note, then reference that note here. This smoke file should track matrix membership, status, `Last Uploaded`, `Last Green`, and **`Last Upload Check`** (date + version from `scripts/reports/wi-release-smoke-registry.yaml` → `UPLOAD-ZIP.hosts[]`).

| Target | Canonical URL / Admin | Login source | Upload method | Publish/unpublish allowed | Last Uploaded | Last Upload Check | Last Green | Status |
|---|---|---|---|---|---|---|---|---|
| WI.com Staging / WordPress.com Atomic Nginx | `https://staging-9959-tobiasbconrad.wpcomstaging.com` / `https://staging-9959-tobiasbconrad.wpcomstaging.com/wp-login.php?loggedout=true&wp_lang=en_US` | [`.env.wicom-staging.local.example`](../.env.wicom-staging.local.example) → `.env.wicom-staging.local`; `WI-COM-STAGING-ACCESS.local.md` | wp-admin upload confirmed; WordPress.com Atomic SFTP/SSH optional when staging mapping is explicit | yes on staging/test only | 2026-06-26 18:48 UTC, `4.13.136` via wp-admin ZIP replace | 2026-07-06 `4.14.76` pass (SSH wp-cli) | 2026-06-28: Standard + AI Evergreen + Custom SC `/wi-p7-custom-sc-reg/` all Reg -> Submit -> TY/Room green (`GREEN_REDIRECT`) | CLEAR for tested Standard + AI Evergreen/Auto + Custom SC; full green once explicit separate Fixed-date UI is defined or confirmed as AI Live |
| Cloudways Staging (Cursor test) | `https://wordpress-1301098-5039235.cloudwaysapps.com` / `/wp-admin/` | `scripts/env/staging-wp-browser.local.env`, `.env.cloudways-staging.local`, `STAGING-ACCESS.local.md` | SFTP/lftp or wp-admin ZIP replace | yes | 2026-06-28, `4.13.211` verified by SFTP download | 2026-07-06 `4.14.76` pass (wp-admin) | 2026-06-28: Standard + AI Evergreen + Custom SC `/wi-p7-custom-sc-reg/` all Reg -> Submit -> TY/Room green (`GREEN_REDIRECT`) | CLEAR for tested Standard + AI Evergreen/Auto + Custom SC; full green once explicit separate Fixed-date UI is defined or confirmed as AI Live |
| Microsoft/IIS server | `https://test-wi-on-asp.premiumasp.net` / `/wp-admin/` | see `.cursor/wi-site-file-change-notes.md` | SFTP previously successful; wp-admin Plugin Upload/Replace also available | yes | 2026-06-28, `4.13.211` via wp-admin ZIP replace | 2026-07-06 `4.14.76` pass (wp-admin replace) | 2026-06-28: Standard + AI Evergreen + Custom SC `/?page_id=122` all Reg -> Submit -> TY/Room green (`GREEN_REDIRECT`) | CLEAR for tested Standard + AI Evergreen/Auto + Custom SC; full green once explicit separate Fixed-date UI is defined or confirmed as AI Live |
| Apache server | `https://wi-on-apache.byethost7.com/wp/` / `/wp/wp-admin/` | see `.cursor/wi-site-file-change-notes.md` | **FTP** `ftpupload.net` **port 21** (not SFTP/22 — blocked); wp-admin ZIP fallback | yes | 2026-07-07 `4.15.12` FTP mirror + activate | 2026-06-28: Standard + AI Evergreen + Custom SC `/wp/wi-p7-custom-sc-reg/` all Reg -> Submit -> TY/Room green (`GREEN_REDIRECT`) | CLEAR — re-smoke Reg after FTP deploy |
| OpenLiteSpeed / LightNode VPS | `https://litespeed-lightnode.webinarignition.com` / `/wp-admin/` | `.env.lightnode-ols-wp.38-54-84-124.local` (from [`.env.lightnode-ols-wp.local.example`](../.env.lightnode-ols-wp.local.example)) | SSH key + `wi-dev/local/wi-lightnode-wp-deploy.sh` (wp-cli); fallback wp-admin ZIP | yes | 2026-07-04, `4.13.472` SSH+wp-cli | 2026-07-06 `4.14.76` pass (wp-admin) | 2026-07-04: plugin version + `wi-registrant-tz.js` 200 public verify | PARTIAL — deploy/access green; full AI smoke matrix pending |

---

<!-- source: .cursor/rules/wi-smoke-test-webinar-timing.mdc -->

# WI — E-Mail-Smoke-Grundlage (Reminder-Timing)

## Kernregel

**Keine Mail-Time-Compression.** Tab8-Zeit = Cron-Sendezeit. Eine Wahrheit.

| Kontext | Reminder-Offsets (Live fixed-date) | Live-Dauer |
|---------|-----------------------------------|------------|
| **Smoke-Hosts** (5-Host-Matrix) — **MAIL-6MIN (kanonisch)** | **2m / 1m / at live / 1m / 1d** nach **Live-Ende** | **1 Minute** |
| **Smoke-Hosts — MAIL-35MIN extended (optional)** | **15m / 5m / at live / 5m / 15m** nach Live-Ende | **5 Minuten** via `WI_WEBINAR_SANDBOX_LIVE_DURATION_MINUTES=5` + legacy offsets filter |
| **Prod / Kunden** | **1 Tag / 1 Stunde / at live** + Slot 4/5 wenn Replay aktiv | echte Kampagnen-Dauer |

Code-Default Prod: `wi_mail_notif_offset_defaults()` in [`inc/wi-mail-notification-schedule.php`](../../inc/wi-mail-notification-schedule.php).

Smoke-Default: `wi_webinar_sandbox_offset_defaults()` + `wi_webinar_sandbox_live_duration_minutes()` in [`inc/wi-webinar-sandbox.php`](../../inc/wi-webinar-sandbox.php).

## MAIL-6MIN — kanonische Smoke-Zeitachse

Prod-Semantik → komprimiert für schnellen Mail-Sub-Smoke (`MAIL-MULTI`, `timing_profile: mail-6min`):

| Slot | Prod | Smoke (MAIL-6MIN) | Mail-ID |
|------|------|-------------------|---------|
| 1 | Tag vorher | 2 Min vor Live-Start | MAIL-R1 |
| 2 | Stunde vorher | 1 Min vor Live-Start | MAIL-R2 |
| 3 | Bei Live | Bei Live | MAIL-R3 |
| 4 | 1 Std danach | 1 Min nach Live-**Ende** | MAIL-R4 |
| 5 | 1 Tag danach | 1 Tag danach | MAIL-R5 |

```
T = Live-Start
Slot 1:  T − 2m
Slot 2:  T − 1m
Slot 3:  T
Ende:    T + 1m
Slot 4:  Ende + 1m = T + 2m
Slot 5:  Ende + 1d (separater Pass / partial OK)
```

**Fast-Grün:** MAIL-V + MAIL-C + R1…R4 in ~6 Min Session. **R5** Folgetag oder `partial`.

## Warum 1 Minute Dauer (MAIL-6MIN)

**Slot 4 und 5 rechnen vom Live-Ende** (`live_start + webinar_start_duration`), nicht vom Live-Start.

| Offset-Typ | Anker |
|------------|-------|
| Slot 1–3 | Live-**Start** (before / at live) |
| Slot 4–5 | Live-**Ende** + Offset (after) |

## Smoke-Hosts (kanonisch)

Gleiche Matrix wie [`wi-ai-webinar-smoke-scope.mdc`](wi-ai-webinar-smoke-scope.mdc):

- Cloudways Staging
- WI.com Staging
- IIS / Apache / OpenLiteSpeed Test-Hosts
- `localhost` / `127.0.0.1`

Helper: `wi_webinar_sandbox_is_smoke_site()` · Host-Liste: `wi_webinar_sandbox_smoke_hosts()`.

## Agent / QA — Pflichtablauf

**Smoke = testen, fixen, erneut testen bis Pflicht-Mails grün.** Host fail → melden, **andere Hosts weiter** (siehe Upload-Gate / Host-Isolation in [`wi-pre-release-smoketest.mdc`](wi-pre-release-smoketest.mdc)).

1. **Nie** globale Compression oder Ratio-Multiplikatoren (P22 entfernt).
2. Tab8 → **Arm timing sandbox (~30 min lead)** auf Smoke-Host:
   - Live in ~30 Min
   - Dauer **1 Min** (MAIL-6MIN)
   - Offsets **2/1/0/1 Min + Slot5 1 Tag**
   - Stale send-claims werden beim Arm freigegeben
3. **Danach** Test-Leads registrieren (nicht vor Arm).
4. Versand **nur** Cron/AS (`schedule_email_live.php`). Kein manueller Massenversand als Timing-Beweis.
5. **Send Email Test** = Inhalt/Links only, nicht Schedule-Proof.

Override (nur Debug): `WI_WEBINAR_SANDBOX_LIVE_DURATION_MINUTES` Env/Constant, Filter `wi_webinar_sandbox_live_duration_minutes`.

## Prod / Release

- Neue Live-Kampagnen: Default-Offsets 1d/1h/0 bleiben.
- Slot 4/5: `off` bei Create, `on` wenn Replay-Video gesetzt.
- **Nie** 1-Min-Dauer auf Kunden-Produktion ohne expliziten Auftrag.

## Verboten

- `wi_p22_mail_time_compression_*` (gelöscht)
- Smoke mit 35/60-Min-Kampagnen-Dauer und Erwartung „schnelle“ Post-Live-Slots ohne Sandbox-Arm
- Site-weite Option die Tab8-Zeiten von Cron-Zeiten trennt

## Cross-Ref

- Mail-Smoke-Matrix: [`wi-multiserver-mail-smoke.mdc`](wi-multiserver-mail-smoke.mdc)
- Sandbox-UI: Tab8 [`UI/app/tab8.php`](../../UI/app/tab8.php)
- 5-Host-Matrix: [`wi-ai-webinar-smoke-scope.mdc`](wi-ai-webinar-smoke-scope.mdc)
- Dashboard: [`plans/SMOKE-DASHBOARD.md`](../../plans/SMOKE-DASHBOARD.md)

