<!-- AUTO-GENERATED by scripts/wi-claude-rules-sync.sh — do not edit. -->
<!-- bundle: 10-coding-journey | sources: 10 .mdc files -->
<!-- source: .cursor/rules/wi-development-guardrails.mdc -->

# WebinarIgnition Development Guardrails

## Before Every Answer

- Review the proposed solution for logical errors, missed edge cases, and conflicts with the WI North Star, Risk-Veto, and Deliverable Loop.
- If uncertain, say explicitly: **"I'm not confident - switching to smaller steps."** Then reduce scope and proceed only with the next verifiable step.
- Before writing code, load the full relevant file(s), not only snippets. For broad or unfamiliar areas, explore the related code paths first.

## Context Loading

- For grid/layout issues, inspect the connected **CSS + PHP + JS** before editing.
- For WooCommerce issues, inspect the relevant **hooks + templates** together.
- For interacting systems such as **WooCommerce + Gutenberg + Video**, say upfront that multiple systems interact and use smaller verified steps.
- Prefer existing local patterns and helpers over isolated fixes that only solve the visible symptom.

## Step Strategy

- Break complex tasks into small, verifiable steps.
- Never intentionally change more than **3 files** in one response unless Tobias explicitly approves the larger scope.
- If a task needs more than **5 steps**, stop and outline the plan first.
- For multi-step code edits, leave a concise checkpoint comment only where it helps future debugging and does not clutter production code:
  `// CHECKPOINT: [what was done] - [date]`
- Do not add checkpoint comments for trivial edits, generated files, pure formatting, or places where a permanent code comment would be noise.

## Coding safety cheatsheet (one page)

Compact defaults for **best coding + not breaking prod**. Details live in linked rules — do not duplicate long checklists here.

### Before coding

- **Understand the blast radius:** Registration, TY, live room, replay, mail, cron, AJAX/REST, enqueue, Freemius → see [wi-participant-journey.mdc](wi-participant-journey.mdc) and [wi-compat-security-speed.mdc](wi-compat-security-speed.mdc). If in doubt, ask once instead of guessing.
- **Load context:** Full file(s) + related CSS/PHP/JS for the same surface. For first PHP touch in a chat, follow [wi-legacy-read-before-touch-14.mdc](wi-legacy-read-before-touch-14.mdc).
- **Browser-Console vor Fix + Debug-Log:** Staging-URL(s) — **Admin-Browser-Console** + **TN-Browser-Console** und WI-relevante Logs **vor** dem Edit prüfen; WI-Fehler im Scope minimal mitfixen — Details + Out-of-scope: [wi-agent-workflow.mdc](wi-agent-workflow.mdc) (*Browser-Console vor Fix + Debug-Log*).
- **Risk gate:** If triggers apply, output **Risk-Veto A/B/C** before editing — [wi-risk-veto.mdc](wi-risk-veto.mdc), [wi-protect-veto-alternatives.mdc](wi-protect-veto-alternatives.mdc). Admin/TN feature removal or hiding: [wi-no-silent-feature-removal.mdc](wi-no-silent-feature-removal.mdc) (Grund + Wiederherstellung A/B/C).

### While coding

- **Smallest diff that solves the task** — match local patterns; no drive-by refactors or unrelated files.
- **Kein Agent-Debug-Ingest:** nie `fetch` zu `127.0.0.1:7283` / `/ingest/` im Ship-Set — [wi-no-localhost-debug-ingest.mdc](wi-no-localhost-debug-ingest.mdc).
- **Hard compat lines:** Do not break existing **shortcodes** or **template names**; do not raise PHP minimum without explicit task; conditional enqueue for heavy assets — [wi-compat-security-speed.mdc](wi-compat-security-speed.mdc).
- **Security defaults:** Escape/sanitize output; `$wpdb->prepare`; nonces + capabilities on admin endpoints — same doc.
- **File budget:** Prefer ≤**3 files** per response unless Tobias explicitly widens scope (see **Step Strategy** above).

### Before “done” (verify, then hand off)

- **PHP:** `php -l` on touched PHP before deploy — [wi-staging-infra.mdc](wi-staging-infra.mdc).
- **Staging-sichtbar:** Bump `Version:` + `WEBINARIGNITION_VERSION` together in `webinarignition.php`, deploy with changed files, `wp cache flush`, **screenshots** of the real check URL — [wi-agent-workflow.mdc](wi-agent-workflow.mdc), [wi-deliverable-loop.mdc](wi-deliverable-loop.mdc). Screenshot storage: [wi-screenshot-hygiene.mdc](wi-screenshot-hygiene.mdc).
- **Git:** No commit/push until Tobias sends **`working ✓`** / **`#Axxx working`** — [wi-agent-workflow.mdc](wi-agent-workflow.mdc), [wi-git-clean-between-tasks.mdc](wi-git-clean-between-tasks.mdc).
- **If not confident:** Say so and shrink the next step to one verifiable change — **Before Every Answer** above.

## When To Stop And Ask For Reasoning

- If the solution becomes unclear mid-task, stop and say: **"This needs deeper analysis. Please switch to Medium reasoning."**
- If risk grows beyond the current task scope, trigger the relevant WI Risk-Veto / Beirat workflow before changing code.

---

<!-- source: .cursor/rules/wi-compat-security-speed.mdc -->

# Kompatibilität, Security, Speed, Admin-UX

Trifft eine geplante Änderung einen der folgenden Punkte, gilt der **Risk-Veto** (`wi-risk-veto.mdc`). Infra/Staging: `wi-staging-infra.mdc`.

## Kompatibilität

- PHP-Minimum aus dem Plugin-Header (`webinarignition.php`) **nicht** anheben ohne expliziten Auftrag.
- **Classic + Block-Theme** berücksichtigen; `wp_is_block_theme()` nicht pauschal für alle Installationen annehmen.
- **Legacy-Shortcodes und Template-Namen** unverändert lassen (siehe auch **`wi-participant-journey.mdc`**).
- **Composer / Node / Vendor-Bumps** nie unaufgefordert.
- **Freemius `is_premium`:** Kanon **`cloudways-freemius-premium-qa.mdc`** (`true` im Repo und auf Staging, Ausnahmen nur explizit).

## Security

- **Nonces** + `current_user_can` auf allen **Admin**-AJAX-/REST-Endpunkten; öffentliche Endpoints dokumentiert absichern.
- **`$wpdb->prepare`** für jede SQL-Variable.
- **Output:** `esc_html`, `esc_attr`, `esc_url`, `wp_kses_post` je nach Kontext.
- **HTTP:** `wp_remote_get` / `wp_remote_post` statt `curl` / `file_get_contents` für externe Requests.
- **Keine Secrets** oder API-Keys ins JS-Bundle; **`STAGING-ACCESS.local.md`** niemals committen.
- **Dateizugriff:** wo möglich `WP_Filesystem` statt roher Pfade.

## Speed

- **Conditional enqueue:** schwere WI-Assets nur auf WI-relevanten Seiten (Registration, Live, TY, Replay, WI-Admin).
- Kein blindes **`SELECT *`** auf großen `wi_*`-Tabellen; **Pagination** und indizierte Spalten bevorzugen.
- **Transients** für wiederholte externe HTTP-Calls (mind. ca. 5 Minuten TTL, sofern sinnvoll).
- Kein **zusätzliches** jQuery im Participant-Frontend, wenn WordPress-Core-jQuery reicht.

## Admin-Usability

- **Menü- und Tab-Reihenfolge** nicht umbauen ohne expliziten Auftrag.
- Keine **Dauer-Admin-Notices** ohne Dismiss und User-Meta (oder gleichwertig).
- **Bulk-Wording-Rewrites** in der Admin-Oberfläche sind **immer** Risk-Veto-fällig.
- **Destruktive Aktionen** (Delete, Reset): `confirm()` oder gleichwertiger Dialog + Nonce.

---

<!-- source: .cursor/rules/wi-participant-journey.mdc -->

# Webinar-Teilnehmer-Reise (höchste Priorität)

Änderungen an diesen Flows **lösen den Risk-Veto aus** (`wi-risk-veto.mdc`). Staging-URLs und Screenshot-Konvention: `wi-staging-infra.mdc`.

## Kritische Flows + Referenz-URLs (Staging)

- **Registrierungs-Landing** (HC + Legacy + FSE): **kanonisch HC** siehe [.cursor/wi-staging-hc-test-webinars.md](../wi-staging-hc-test-webinars.md) — Evergreen Reg https://wordpress-1301098-5039235.cloudwaysapps.com/testing-the-live-reg-webinar/ (id=7), Live Reg https://wordpress-1301098-5039235.cloudwaysapps.com/2025-11-15-tobias/ (id=8). Ältere Slugs mit `…-3/` sind nur Beispiele und können nach DB-Restore **ohne gültige Kampagne** sein.
- **Opt-in / Double-Opt-in-Mail** (Inhalt, Links, Platzhalter, SPF-DKIM-Thema nur mit User).
- **Thank-You / Countdown:** HC-Beispiele: Evergreen TY https://wordpress-1301098-5039235.cloudwaysapps.com/testing-the-live-reg-webinar/?confirmed&live=&lid=e52670c95b494350f944a9cc7f69a69085967d5a&code= — Live TY https://wordpress-1301098-5039235.cloudwaysapps.com/2025-11-15-tobias/?confirmed&lid=6f865f732dac1964423c7e8ffabd97fb09da0c38&code= — Body-Klassen **`wi-wb-registration-landing`**, **`wi-ty-gb-page`** beachten (siehe **`wi-staging-infra.mdc`**). Ältere Fallback-`lid` auf `/2025-11-14/` können nach Restore ungültig sein.
- **Live-Webinar:** `?live&webinar&lid=…` — **HC Live** zuerst über Registrierung `2025-11-15-tobias` testen; älteres Beispiel: https://wordpress-1301098-5039235.cloudwaysapps.com/123-2/?live&webinar&lid=89e1c0134b76386667d74c61ea56a32583073aa2&watch_type=live
- **Replay** (gleiche Teilnehmer-Erwartung: klarer Einstieg, keine kaputten CTAs).
- **Post-Live-Offer / Reminder-Mails** (Text, Links, Tracking nur mit explizitem Auftrag + Consent-Pfad).

## Harte No-Gos (Hard-Stop, nicht nur Veto-Warn)

- **Breaking-Change** an existierenden **Shortcodes** oder **Template-Namen** (`[webinarignition_*]`, `page-webinar-registration`) — Bestandskunden nutzen diese massenhaft.
- Neue **blockierende** externe JS/CSS-Requests im Participant-Frontend (ohne Auftrag und ohne LCP-/Privacy-Klarheit).
- **Formular-Feld-Änderungen** ohne DB-Migrationsplan und ohne Rückwärtskompatibilität zu bestehenden Leads.
- **Tracking / Third-Party-Pixel** ohne explizite User-Aufgabe und ohne dokumentierten Consent-Pfad.
- **Modal/Popup** vor dem Registration-Submit (Friction, Abbruch, Vertrauen).

## Weiche Checks (Default-Option A muss sie erfüllen)

- **Mobile 375×812:** Haupt-CTA bleibt nutzbar („above the fold“ im Sinne von sofort sichtbar/tappbar ohne Trick).
- Keine neuen **LCP-relevanten** Bilder > 200 KB ohne `loading="lazy"` / Format- und Pfad-Check.
- **Fehlermeldungen:** verständlich, nicht-technisch, **ohne** Stacktraces, SQL oder Server-Dateipfade im Participant-UI.
- **Trust-Signale** nicht entfernen (Privacy-Link, seriöser Absender-Kontext, Zeitzone nachvollziehbar).
- **AJAX im Participant-Flow:** `check_ajax_referer` bzw. öffentliche Nonces wo vorgesehen, Capability wo Admin; Responses über `wp_send_json_*` wo passend.

## Pflicht-Screenshot-Set bei Participant-Änderungen

- **Desktop + Mobile** der geänderten URL (1440×900 und 375×812, siehe **`wi-staging-infra.mdc`**).
- **WI-Grid-Seiten:** vor Screenshot **4–6 Sekunden** warten (z. B. Playwright `waitForTimeout(5000)`), sonst verfälschtes Layout.

---

<!-- source: .cursor/rules/wi-page-surfaces-separated.mdc -->

# WI — Seiten-Surfaces immer GETRENNT halten (hart)

## Grundregel (Tobias 2026-06-10, global)

Jede Teilnehmer-Phase ist eine **eigene Seite / eigener Surface** — niemals zwei Phasen auf eine Seite mischen:

| Surface | Zweck | Niemals mischen mit |
|---|---|---|
| **Registration (Reg)** | Opt-in-Formular, Anmeldung | TY, Webinar-Raum, Ended |
| **Thank-You (TY)** | Bestätigung nach Anmeldung, Countdown, Calendar, Reminder-Hinweis | Reg, Webinar-Raum |
| **Webinar-Raum (Live/Replay)** | Player, Chat, CTA, Q&A | Reg, TY, Ended |
| **Ended / Closed** | Webinar vorbei, Replay-Hinweis / Offer | Reg, Live |

**Warum:** Ein Surface = ein klarer Zustand. Mischt eine Seite Reg + TY, entscheidet der Block-/Shortcode-Typ den Modus (`$shortcode_settings['page']`), NICHT die URL (`?confirmed`). Ergebnis: `?confirmed&lid=` zeigt trotzdem das Reg-Formular. Genau dieser Fehler trat am 2026-06-10 auf webinarignition.com (Kampagne 10, HC) auf.

## HC vs GB — TY-Pfad-Unterschied (wichtig)

- **HC (HardCoded, Engine seit 2013):** hat eine **hardcoded TY-Seite** über den Funnel auf der Haupt-Webinar-Permalink mit `?thankyou&lid=...`.
  - Beispiel (Prod, Kampagne 10): `https://webinarignition.com/the-marketing-sales-webinar-driving-school/?thankyou&lid=[lead_id]`
  - Der HC-Funnel (`webinarignition_template_cb`) rendert TY direkt — Reg/TY/Live/Ended sind unterschiedliche `?`-Zustände auf der Haupt-Permalink ODER separate WI-Wizard-Seiten.
- **GB (Gutenberg):** TY ist eine **eigene WP-Seite** (`custom_thankyou_page` / `custom_ty_url`) oder ein dedizierter GB-TY-Block-Surface. Native Theme rendert.

## GB — Webinar-Raum ≠ eigene Seite (Modern Room)

- **Default (ohne `custom_webinar_page`):** Der **Webinar-Raum** (Modern Room) wird auf der **Registrierungs-URL** per Query (`?live&webinar&lid`) gerendert, nicht auf einer separaten GB-Seite.
- **Gleicher Slug, anderer Modus:** Reg-Formular vs. Live-Raum unterscheidet sich durch URL-Parameter + Master-Switch, nicht durch Permalink allein.
- Admin-Preview „Webinar Page“ (tab2) muss den **Raum** zeigen, nicht das Reg-Formular (Host-Login + `preview=true` + `lid=11111`).
- Kanonisch: [`wi-modern-room-canonical.mdc`](wi-modern-room-canonical.mdc), [`wi_resolve_webinar_room_base_url()`](../inc/wi-builder-context.php).

## Konsequenz für Auto-Register / Redirect-Bau

- Der TY-Redirect (`inc/lp/auto-register.php`, `webinarignition_get_thankyou_confirmed_url`) muss auf den **korrekten Surface des jeweiligen Engine-Typs** zeigen:
  - **HC:** `?thankyou&lid=` (bzw. `?confirmed` nur wenn dieser Zustand wirklich TY rendert) auf der Haupt-Webinar-Permalink — NICHT auf eine Reg-Opt-in-Seite.
  - **GB:** dedizierte TY-Seite.
- Eine Reg-Seite (mit `reg_optin`-Block) darf **niemals** das Redirect-Ziel für `?confirmed` sein, wenn sie nicht selbst zur TY umschalten kann.

## Agent-Pflicht

- Vor jedem Redirect-/TY-Routing-Fix: **erst Engine-Typ prüfen** (`wi_is_hc()` / `wi_is_gb()`), dann den richtigen TY-Surface wählen.
- Bei „weiße Seite“ oder „zeigt Reg statt TY“: prüfen, ob zwei Surfaces auf einer Seite gemischt wurden — das ist der häufigste Grund.
- Cross-Ref: Router-Trennung Plan `.cursor/plans/p17_router_split_hc_gb.plan.md`, `wi-participant-journey.mdc`.

## GB-first / HC-frozen (P18, 2026-06-10)

- **Neue Webinare:** immer GB (Wizard-Default bereits prod).
- **HC:** nur Legacy/Import; Funnel-Pfad (`wi_resolve_render_path` → `hc_funnel`) nicht ausbauen.
- **URL-Builder:** kanonisch `inc/wi-participant-urls.php` — keine parallelen TY-Builder.

---

<!-- source: .cursor/rules/wi-modern-room-canonical.mdc -->

# WI — Modern Room (kanonisch, dauerhaft)

## Drei Phasen + ein Raum (heute)

| Phase | Was der TN sieht | WP-Seite (GB-Default) |
|-------|------------------|------------------------|
| **Registrierung** | Anmeldeformular | Eigene Reg-LP |
| **Danke-Seite** | Countdown, Kalender | Eigene TY-LP (GB) oder `?thankyou` (HC) |
| **Webinar-Raum** | **Modern Room** (Player, Chat, CTA, Q&A) | **Meist dieselbe Reg-URL** mit `?live&webinar&lid` |

**Modern Room** = hardcodiert [`inc/lp/webinar-modern.php`](../inc/lp/webinar-modern.php). Default für **GB + HC**, **Live + Evergreen**. Keine eigene Gutenberg-„Webinar-Seite“ im Default-Fall.

**Später (nicht Default):** HCR-Legacy (Migrations-Zwischenschritt) und HSR-Room (nur Gutenberg). Nicht mit Modern Room verwechseln.

## Raum-URL (Wurzel)

Kanonisch: [`wi_resolve_webinar_room_base_url()`](../inc/wi-builder-context.php) und `WebinarignitionManager::webinarignition_get_permalink( $data, 'webinar' )` (delegiert an Resolver).

Reihenfolge: `custom_webinar_page` (wenn gesetzt) → **Reg-Permalink** → Kampagnen-Post. **Nie** Thank-You-Fallback für GB.

Admin-Preview (tab2 „Webinar Page“): [`wi_webinar_admin_dashboard_preview_url()`](../inc/wi-builder-context.php) = Raum-Basis + `live=1&webinar=1&lid=11111&watch_type=live&preview=true`. Preview zeigt **immer** den Raum, unabhängig vom Master-Switch.

## Master-Switch (Host tab1)

Zustände: `countdown | live | replay | closed`. Realtime leitet Teilnehmer um ([`assets/wi-master-switch-participant.js`](../assets/wi-master-switch-participant.js), URLs aus `webinarignition_master_switch_realtime_data`).

- countdown → live: Danke/Countdown → **Webinar-Raum**
- live → closed: Raum → **Beendet**
- closed → live: Beendet → **Raum**
- live → countdown: Raum → **Danke/Countdown**
- → replay: **Replay** (Modern Room Replay-Modus)

## Skip-TY bei live

Link mit gültiger `lid` + Master-Switch = `live`: **direkt Raum** rendern, Danke-Seite überspringen (HC + GB). Spart Ladezeit bei vielen TN.

## Mail-Link „Zeit fürs Webinar“

Raum-Basis + `lid`. Server entscheidet per Switch: countdown = TY/Countdown, live = Raum.

## QA (Agent-Pflicht)

1. **URL:** Preview/Join ≠ thank-you-Slug; finale URL behält `live`/`webinar`/`preview` nach Redirects (eingeloggt).
2. **Bild:** Raum = Player/`#webinarContent`, **kein** „Register now“. Gast ohne Login → Reg-Formular ist **Schutz**, kein URL-Bug.

Cross-Ref: [`wi-page-surfaces-separated.mdc`](wi-page-surfaces-separated.mdc), [`wi-screenshot-hygiene.mdc`](wi-screenshot-hygiene.mdc), [`wi-modern-room-journey-smoke-default.mdc`](wi-modern-room-journey-smoke-default.mdc) (Default Full-Matrix Smoke).

---

<!-- source: .cursor/rules/wi-legacy-read-before-touch-14.mdc -->

# WI: PHP vor erstem Edit (Legacy-Check)

Vor der **ersten** Änderung an einer **PHP**-Datei, die in **diesem Chat** noch **nicht vollständig** gelesen wurde — **ohne User-OK**, Agent führt selbst aus:

1. **Datei vollständig lesen** (gesamter Inhalt).
2. **In der Datei:** nach `require` / `require_once` / `include` / `include_once` suchen.
3. **Repo-weit:** wer lädt **diese** Datei per `require*` / `include*` (Pfad/Dateiname treffend grep-en)?
4. **Repo-weit:** `add_action` / `add_filter` mit Callbacks, die **in dieser Datei** definiert sind (Funktions-/Klassenmethoden-Namen aus der Datei als grep-Muster).
5. **Klassifizieren:** **`sicher`** nur wenn **≤2** sichtbare Abhängigkeits-Kanten (z. B. Includes in der Datei ➕ externe Einbindungen/Caller, grob gezählt) **und** in dieser Datei **keine** Registrierung auf **`init`**, **`wp`**, **`template_redirect`**, **`save_post`**, **kein** AJAX-/REST-Handler. Sonst **`komplex`**.

- **`sicher`:** direkt weiterarbeiten.
- **`komplex`:** Scope auf das Minimalste; **ein Satz** im Chat, was die Suche zeigte, dann weiter.

**Kein Pflichtlauf:** nur CSS/JS, **neue** Datei (noch nicht im Repo), PHP bereits **komplett** in diesem Chat gelesen, reine **Doku** / **`.mdc`**.

Cross-Ref: **`wi-development-guardrails-13.mdc`**. Keine Wiederholung von Inhalten aus **`wi-development-guardrails-13.mdc`** oder **`wi-protect-veto-alternatives-3.mdc`**.

---

<!-- source: .cursor/rules/wi-no-localhost-debug-ingest.mdc -->

# WI — Kein Agent-Debug im Plugin

## Problem (wiederkehrend)

Cursor-Agents fügen beim Debuggen Instrumentierung ein, die auf **Staging/Live** stört:

- `fetch('http://127.0.0.1:7283/ingest/...')` → Chrome-Popup *„Auf andere Apps und Dienste auf diesem Gerät zugreifen"*
- `#region agent log` Blöcke in JS/PHP
- `sessionStorage.setItem('wi_debug_…')` oder `wi-debug-*.ndjson` auf dem Server

**Das ist kein Produkt-Feature. Vor jedem Handoff entfernen.**

## Hartes Verbot (Ship-Set)

In allem was deployt wird (`webinarignition.php`, `inc/`, `UI/`, `admin/`, `assets/`, `templates/`, `css/`):

| Nie committen | Beispiele |
|---|---|
| Loopback-Ingest | `127.0.0.1:7283`, `localhost:7283`, `/ingest/148f6934` |
| Agent-Marker | `#region agent log`, `wiDbg831`, `__wiDebug831`, `X-Debug-Session-Id` |
| Session/File-Debug | `wi_debug_8a7220`, `wi-debug-8a7220.ndjson`, `wi_debug_log_8a7220` |
| „Nur auf localhost“-Guards | Code bleibt im Repo und kommt beim nächsten Agent-Task zurück |

## Erlaubt

- `127.0.0.1` / `localhost` in **PHP-Host-Arrays** für Sandbox-Erkennung (`inc/wi-webinar-sandbox.php`) — **ohne** JS-Fetch und ohne NDJSON-Logger.

## Agent-Pflicht

1. Nicht einbauen, auch nicht temporär.
2. Vor Deploy: `./scripts/wi-no-localhost-ingest-check.sh` (auch in `wi-syntax-check.sh`).
3. Treffer: **komplett löschen**, nicht guarden.

## Bekannte Hotspots

- `assets/webinarignition-admin-dashboard.js` — Tab/Editor-Reload
- `UI/editapp.php` — `wiEarlyShowTab()`
- `inc/wi-webinar-sandbox.php` — Sandbox arm/disarm

## Cross-Ref

[wi-agent-workflow.mdc](wi-agent-workflow.mdc) · [cloudways-freemius-premium-qa.mdc](cloudways-freemius-premium-qa.mdc)

---

<!-- source: .cursor/rules/wi-no-silent-feature-removal.mdc -->

# WI — No Silent Feature Removal

## Verbot (hart)

UI-Elemente, Settings, Dropdowns, Admin-Tabs oder Teilnehmer-Flow-Schritte **nicht** entfernen, ausblenden oder auf „always on“ erzwingen ohne dokumentierte Zustimmung von Tobias im Chat.

## Trigger

Jede Änderung an:

- **Admin-Ablauf:** Create, Settings, Wizard, Mail-Tab, Listen, Editor
- **Teilnehmer-Journey:** Reg, TY, Live, Replay, Cookies, Prefill, Redirects

## Pflicht vor Code

1. `AskQuestion` mit A/B/C (★ = Agent-Empfehlung)
2. Risk-Veto wie in [`wi-risk-veto.mdc`](wi-risk-veto.mdc)
3. **Änderungs-Protokoll** (alle Felder):

```
Änderung: [was ist anders als vorher]
Grund: [warum — Commit, Task, technischer Hintergrund]
Status: entfernt | versteckt | geändert | wiederhergestellt | geplant
Wiederherstellung:
  A — [sicherster Weg zurück / beibehalten]
  B — [Mittelweg]
  C — [Alternative / bewusst anders lassen]
Rollback: [1 Zeile git restore / Revert]
```

## Pflicht nach Umsetzung / vor `working ✓`

Im Chat kurz wiederholen:

*„Wir haben X [entfernt|geändert|zurückgesetzt], weil Y. Wiederherstellung: A/B/C.“*

## Nach `working ✓`

Offene Consent-Fragen **erneut stellen** (gleiche Optionen + Grund), bis Tobias antwortet. Kein Commit mit offenen ⚠ zu Journey/Admin-Features.

## Erlaubt ohne Extra-Frage

Reine Bugfixes ohne Verhaltensänderung, Copy-Typos, CSS ohne Funktionsverlust (wenn im Task explizit).

## Laufendes Log

Bei größeren Tasks: [`.cursor/wi-change-decisions.md`](../wi-change-decisions.md) (lokal, gitignored) oder aktiver Plan.

## Cross-Ref

[`wi-development-guardrails.mdc`](wi-development-guardrails.mdc) · [`wi-task-scope-choice.mdc`](wi-task-scope-choice.mdc) · [`wi-participant-journey.mdc`](wi-participant-journey.mdc)

---

<!-- source: .cursor/rules/wi-profi-plugin-principle.mdc -->

# WI — Profi-Plugin-Prinzip

## Regel (hart bei neuen Features)

Wenn eine Funktion auf WordPress.org durch ein **etabliertes Profi-Plugin** gut abgedeckt ist, baut WebinarIgnition **keinen parallelen Stack** (eigene SMTP-UI, eigener Shop, eigenes Social-OAuth, …).

Stattdessen:

1. **Empfehlen** (Copy, Preflight, Setup-Wizard, Docs)
2. **One-Click-Installation anbieten**, wo WordPress es hergibt (`plugin-install.php`, bestehende WI-Install-Patterns)
3. **Integration nur über WordPress-Standard-APIs** (`wp_mail`, WooCommerce-Hooks, Shortcodes/Blocks des Partner-Plugins)
4. **WI-Kern** = Webinar-Logik (Timing, Leads, Templates, Queues, Bounce, Journey) — nicht Infrastruktur pflegen, die ein Plugin-Betreiber besser wartet

## Kanonische Beispiele (Referenz)

| Bedarf | Profi-Plugin (wp.org) | Nicht in WI ausbauen |
|--------|-------------------------|----------------------|
| E-Mail / SMTP / Logs | **SureMail** (+ SES/Brevo) | Eigenes WI-SMTP-Tab, `phpmailer_init` für Host-Credentials |
| Shop / Checkout | **WooCommerce** | Eigenes Cart/Checkout |
| Social Registration | **Nextend Social Login and Register** (o. ä.) | Eigenes OAuth/Provider-Stack |

## Pre-Build-Check (Pflicht vor großem Feature)

**Trigger „groß“:** neues Subsystem, neue Admin-Settings für Infrastruktur, >~3 Dateien oder Participant-Journey / Mail / Payment / Auth.

Vor Umsetzung im Chat **kurz** ausfüllen:

```
Profi-Plugin-Check
- Problem in 1 Satz:
- Gibt es ein wp.org-Profi-Plugin? (Name + Link)
- WI-Integration: welche WP-API / Hooks?
- Was bleibt in WI? (nur Fachlogik)
- Legacy WI-Code: deprecaten statt ausbauen? (ja/nein)
- Entscheidung: Plugin-Empfehlung | Minimal-WI | Ausnahme begründet
```

**Ausnahme** nur mit explizitem User-OK oder wenn kein Plugin den Job erfüllt (kurz begründen).

## Verhalten bei Legacy

- Bestehende WI-Optionen/Tabs **nicht** breaking entfernen
- UI: Deprecation-Hinweis + Link zum empfohlenen Plugin
- Kein neuer Wartungsaufwand für deprecated Pfade

## Cross-Referenzen

- E-Mail: Master-Plan `wi_smtp_mail_strategie` (SureMail, Bounce, AS)
- `wi-participant-journey.mdc`, `wi-development-guardrails.mdc`

## E-Mail — Sonderfall (Klarstellung)

- WI **bündelt kein** SMTP-Plugin; Versand läuft immer über **`wp_mail()`** (PHPMailer).
- **From Name / From Email** kommen von **WebinarIgnition** (pro Webinar/Kampagne — bestehende Einstellungen).
- **Ohne** SureMail/SMTP-Plugin können Notifications und Preflight-Test-Mails **trotzdem** funktionieren (Hosting-`mail()`).
- SureMail = **Empfehlung** für Zustellbarkeit/Skalierung — **nicht** Hard-Stop in Preflight.
- Preflight: getrennte Zeilen — (1) Versand-Test grün/rot, (2) SMTP-Plugin-Empfehlung gelb/grün, blockiert Gesamt-Readiness nicht.

---

<!-- source: .cursor/rules/wi-server-load-check.mdc -->

# WI — Server-Load-Check vor Abschluss (Pflicht)

Bei DB/AJAX/Cron/Hooks/Polling: Pflicht-Block vor Umsetzung und vor Abschluss. VETO-EXTREM bei >50 DB-Writes/Min oder >100 AJAX/s bei 600 TN.

Siehe wi-security-check-before-done.mdc für Format. Felder: DB-Last, AJAX-Frequenz, Cron/Hooks, Externer Traffic, Cache, Memory, 600-TN-Felix-Gate.

