16 KiB
Umsetzungsplan — Marken-Klarheits-Check
Kontext: Inbound-Magnet aus dem Konzept (marken-klarheits-check.md). 5 Fragen mit 4-Stufen-Skala + optionalem Freitext, deterministischer Reifegrad im Frontend, optionale KI-Auswertung über einen serverseitigen Laravel-Proxy (Anthropic). Referenz für Fragen/Skalen/Prompt/JSON-Vertrag bleibt Klarheits-Check_Prototyp.html.
Lebendes Dokument. Nach jedem Checkpoint aktualisieren. Wiederaufnahme: zuerst 📍 Aktueller Stand lesen, dann beim ersten offenen
[ ]-Checkpoint weiterarbeiten. Jeder Checkpoint endet konsistent (Tests grün, nichts halb-fertig).
📍 Aktueller Stand (immer zuerst lesen)
- Phase: ✅ 1–4 fertig, Phase 5 fast durch (CP 5.1/5.2/5.3 erledigt) + Prompt-Engineering eingebaut.
Offen: nur noch CP 5.4 — Ton-Kalibrierung mit echten Keys +
npm run build+ manuelle Prüfung beider Modi/mobil. Keys liegen in.env,config/services.phpist eingerichtet (anthropic + openai). - Zuletzt erledigt: Phase 3 —
KlarheitsCheckController@auswerten+ RoutePOST /klarheits-check/auswerten(Nameklarheits-check.auswerten). Validierung (5×{skala:0–3, text:nullable|max:5000}), Rate-Limit 10/IP/10min → 429. Anthropic-Call via LaravelsHttpnur bei Freitext, Modell/Key/Timeout ausconfig('services.anthropic.*'), System-Prompt ausconfig('klarheits_check.ki.system'). JSON geparst + auf den Vertrag normalisiert; jeder Fehler (kein Key, Timeout, Fehlerstatus, kaputtes JSON) → deterministischer Fallback. Keine Persistenz. 6Http::fake()-Tests. 71/71 Tests grün, Pint sauber. - Als Nächstes: CP 5.4 — Testreihe via
php artisan klarheits-check:probe(Default OpenAI) durchspielen, Ton inconfig('klarheits_check.ki.system')nachschärfen, dannnpm run build+ manuelle Prüfung beider Wirkungs-Modi/mobil. Legaltext in CP 4.2 bitte gegenprüfen (Anbieterwahl, SCC/DPA). - Branch:
feat/markemacht-laravel-migration. - Modell bestätigt (via
claude-api-Skill):claude-sonnet-4-6, kein Datums-Suffix; Headerx-api-key+anthropic-version: 2023-06-01. Tests laufen ohne echten Key überHttp::fake(). - Dual-Anbieter: umschaltbar über
KLARHEITS_CHECK_KI(anthropic|openai) →config('klarheits_check.ki.provider'). OpenAI via Chat Completions (config('services.openai.*'),response_format: json_object,max_completion_tokens). Beide Anbieter teilen System-Prompt + JSON-Vertrag; identischer Fallback. 72/72 Tests grün.
Gesperrte Entscheidungen (vom User bestätigt)
- Ort/URL: eigene, teilbare Seite
/klarheits-check(LinkedIn-Magnet, Umami, SEO). - Trigger: vertikaler Hochkant-Tab rechts (fix an der Bildschirmkante), verlinkt direkt
auf
/klarheits-check(springt zur Seite — Overlay wurde verworfen, User-Entscheidung). Auf Mobil horizontaler Pill unten rechts (gedrehte Tabs sind dort unpraktisch). - Reuse: Die Check-Markup-Quelle liegt als Blade-Partial vor (
web.partials.klarheits-check), bleibt also wiederverwendbar, falls später doch ein Overlay o. Ä. gewünscht wird. - Kein Livewire: clientseitiger Quiz-State + ein einziger KI-Call → schlankes JS/Alpine + Controller-Endpoint. (Anders als Audit-Formular — bewusst, gemäß Konzept.)
- KI nur bei Freitext: ohne Freitext kein Anthropic-Call (Datensparsamkeit). Deterministisches Ergebnis greift immer; KI schärft nur.
- HTTP-Weg: Laravels
Http-Client (keine neue Composer-Abhängigkeit; ein POST genügt). - Modell: Sonnet (gemäß Konzept; günstig für ein kostenloses, reichweitenstarkes Tool).
Exakte Modell-ID beim Backend-Bau (CP 3.x) via claude-api-Skill bestätigen — Prototyp nennt
claude-sonnet-4-6; keine Datums-Suffixe anhängen. - API-Key:
ANTHROPIC_API_KEYin.env(Server + lokal zum Echt-Testen). Erst ab Phase 3 nötig; Tests nutzen einen gemockten HTTP-Client.
Fortschritt (Überblick)
Phase 1 — Frontend (Check-Seite, ohne KI) · braucht keinen Key ✅
- CP 1.1 Route
/klarheits-check(routes/marketing.php) + Seiteweb.klarheits-checkim Marketing-Layout - CP 1.2 Check-Partial
web.partials.klarheits-checkausconfig/klarheits_check.php; scoped CSSkc-*(Tokens) - CP 1.3 Quiz-JS
resources/js/web/klarheits-check.js(Vite-Input + Layout-@vite); Fetch+Fallback; CSRF-Meta im Layout - CP 1.4 Pest
KlarheitsCheckTest(Seite rendert, 20 Optionen, JS/CSRF) — 63/63 grün, Build erzeugt
Phase 2 — Hochkant-Tab ✅ (Overlay verworfen: Tab springt direkt zur Seite)
- CP 2.1 Vertikaler Tab rechts im Marketing-Layout (global),
writing-mode: vertical-rl, mobil als horizontaler Pill unten rechts; auf/klarheits-checkselbst via@unlessausgeblendet Overlay/Drawer— entfällt: Tab ist ein<a>aufroute('klarheits-check')(User-Entscheidung)- Test: Tab vorhanden auf
index, fehlt auf der Check-Seite
Phase 3 — Backend KI-Proxy ✅
Umgesetzt.
app/Http/Controllers/Web/KlarheitsCheckController.php(auswerten), Route inroutes/marketing.php. System-Prompt +max_tokensliegen inconfig/klarheits_check.php(ki.*) als einzige Wahrheit neben Fragen/Reifegrad.gradLine()serverseitig gespiegelt zum Frontend.
- CP 3.1
KlarheitsCheckController@auswerten+ RoutePOST /klarheits-check/auswerten(klarheits-check.auswerten). Validierungantworten= 5×{skala:0–3 (required), text:nullable|max:5000}. Rate-Limit 10/IP/10min → 429 (mit deterministischem Body). Deterministisches Ergebnis als Baseline. - CP 3.2 KI-Call nur bei Freitext, Anbieter via
config('klarheits_check.ki.provider')(KLARHEITS_CHECK_KI): Anthropic (Http::withHeadersx-api-key/anthropic-version,config('services.anthropic.*')) oder OpenAI (Http::withToken,config('services.openai.url'), Chat Completions mitresponse_format: json_object+max_completion_tokens). Beide teilen System-Prompt (config('klarheits_check.ki.system')) und Vertrag —anthropicText()/openaiText(). - CP 3.3 Antwort-Text aus
content[]extrahiert, ```json-Zaun entfernt,json_decode, auf den Vertrag normalisiert (vertragNormalisieren):gesamt,spiegel:[{nr,text}],luecken[],stimmigkeit[],schluss. - CP 3.4 Timeout aus Config +
try/catch (Throwable)+ leerer Key →null→ deterministischer Fallback (Tool funktioniert immer). Keine Persistenz. - CP 3.5
tests/Feature/Web/KlarheitsCheckAuswertenTest.php— 6Http::fake()-Tests: Erfolg (+ Modell/ Header/System-Prompt geprüft), kaputtes JSON → Fallback, Fehlerstatus → Fallback, kein Freitext → kein KI-Call, Validierung (422), Rate-Limit (429). 71/71 grün.
Phase 4 — Datenschutz ✅
- CP 4.1 Hinweis
.kc-privacyinweb.partials.klarheits-check(über dem „Jetzt auswerten"-Button): Freitext → KI-Dienst (Anthropic bzw. OpenAI, USA), keine Speicherung, ohne Text rein lokal; Link aufdatenschutz#ki-auswertung. - CP 4.2 Datenschutz-Absatz „6. Marken-Klarheits-Check (KI-Auswertung)" (Anker
#ki-auswertung) inweb.datenschutz: nur Skala = lokal; nur bei Freitext Übermittlung; weder Name/E-Mail/IP; keine Speicherung; kein Training; Rechtsgrundlage Art. 6 (1) a, US-Transfer via Standardvertragsklauseln. 2 neue Tests. 74/74 grün.
Phase 5 — Tests, Ton, Messung, Build
- CP 5.1 Pest: Routentests, Controller (gemockter HTTP-Client: Erfolg, KI-Ausfall→Fallback, Validierung, Rate-Limit)
- CP 5.2 Pint, Gesamt-Suite grün
- CP 5.3 Umami-Events in
klarheits-check.js(Tracker self-hosted, im Marketing-Layout geladen):klarheits-check-gestartet(erste Auswahl),klarheits-check-abgeschlossen({scharf,unscharf,offen,mit_text,ki}— Reifegrad-Verteilung + Flags, kein Freitext),klarheits-check-audit-klick.window.umami-Guard → no-op ohne Tracker. - CP 5.4 Ton-Kalibrierung (Testreihe inkl. Floskeln),
npm run build, manuelle Prüfung beide Modi/mobil
Später (separat, nur notiert)
- Karussell-Ableitung (Hebel B), A/B der Fragentexte, EU-Datenresidenz via Bedrock/Vertex falls gefordert.
Architektur-Notizen
- Datenfluss: Browser sammelt 5 Skalen + optionale Texte → deterministischer Reifegrad lokal →
bei Freitext:
POST /klarheits-check/auswerten(eigene Domain, CSRF) → Controller baut Prompt, ruft Anthropic serverseitig, validiert JSON → zurück an Browser → Render. Key verlässt nie den Server. - HTTP-Weg (gesperrt): Laravels
Http-Client, keine neue Composer-Abhängigkeit. - Modell (gesperrt): Sonnet. Finale Modell-ID beim Bau via
claude-api-Skill bestätigen (config('services.anthropic.model'), Defaultclaude-sonnet-4-6) — keine Datums-Suffixe. - Sicherheit: Prototyp ruft Anthropic direkt aus dem Browser (Zeile 186–189) — wird durch den serverseitigen Proxy ersetzt; der Key verlässt nie den Server.
Changelog (Arbeitsprotokoll)
| Datum | Checkpoint | Ergebnis / Notiz |
|---|---|---|
| 2026-06-18 | Setup | Plan angelegt. UX gesperrt: eigene Seite /klarheits-check + Hochkant-Tab rechts → Overlay. HTTP-Weg=Http-Client, Modell=Sonnet gesperrt. |
| 2026-06-18 | Phase 1 | config/klarheits_check.php (Fragenkatalog), Seite + Partial + kc-*-CSS-Tokens, Quiz-JS (Fetch+Fallback), CSRF-Meta. Tests 63/63, Build ok. |
| 2026-06-18 | Phase 1 · UX | Geführte Navigation: „Check starten"-Button → Frage 1; pro Frage „Weiter"-Button (erscheint nach Auswahl); Freitextfeld nach Auswahl dezent magenta hervorgehoben (ohne Fokus); Submit → „Jetzt auswerten"; alert ersetzt durch Inline-Fehler mit „Zur offenen Frage"-Sprung. Tests 64/64. |
| 2026-06-18 | Phase 1 · UX2 | „Check starten" als Anker #check in den Hero verschoben (raus aus Partial); im Ergebnis-Zustand nur noch „Neu starten" (Start-Link + „Jetzt auswerten" ausgeblendet). Tests 64/64. |
| 2026-06-18 | Phase 1 · UX3 | Start-Link scrollt sanft (JS); [data-kc-submit]/[data-kc-start-link] explizit hidden (sonst überstimmt .btn); Hint-Text + .kc-actions-Linie entfernt; „Neu starten" hinter den Audit-CTA verschoben. Tests 64/64. |
| 2026-06-18 | Phase 2 | Hochkant-Tab rechts (.kc-tab, vertikal; mobil Pill unten rechts), Link auf /klarheits-check, auf der Seite selbst ausgeblendet. Overlay verworfen. Tests 65/65, Build ok. |
| 2026-06-19 | Phase 3 | KI-Proxy: KlarheitsCheckController@auswerten + POST /klarheits-check/auswerten. Validierung, Rate-Limit 10/IP/10min, Anthropic-Call (Http, nur bei Freitext) via config('services.anthropic.*') + System-Prompt aus config('klarheits_check.ki.system'), JSON→Vertrag normalisiert, jeder Fehler → deterministischer Fallback, keine Persistenz. Modell claude-sonnet-4-6 via claude-api-Skill bestätigt. 6 Http::fake()-Tests. 71/71 grün, Pint sauber. |
| 2026-06-19 | Phase 1 · UX4 | Ergebnis-Hinweis: ohne Freitext zeigt das Ergebnis Eyebrow „Statische Auswertung" + Callout .kc-r-hint („Möchten Sie mehr Klarheit und eine präzise Auswertung? … Felder ausfüllen"). Mit Freitext Eyebrow „Ihre Auswertung", kein Callout. Rein clientseitig (render() in klarheits-check.js), CSS-Token. npm run build nötig. |
| 2026-06-19 | Phase 5 · CP 5.3 | Umami-Events in klarheits-check.js (Tracker self-hosted, Layout Z. 60): klarheits-check-gestartet (erste Auswahl, einmalig), klarheits-check-abgeschlossen ({scharf,unscharf,offen,mit_text,ki}, kein Freitext), klarheits-check-audit-klick. window.umami-Guard → no-op. npm run build nötig. |
| 2026-06-19 | Belegter Grad | Designfehler behoben: erste Spalte zeigte den Skalen-Grad, der Spiegeltext den belegten — Widerspruch (SCHARF über „nicht prüfbar"). Vertrag um spiegel[].grad (scharf/unscharf/nicht entschieden) erweitert: Validierung als Pflichtfeld (fehlt/ungültig → Fallback), Frontend liest grad für Label+Farbe statt der Skala, Skala-Auswahl raus aus der Stufen-Spalte. Fallback-Ehrlichkeit: Freitext ohne belegten Grad (KI aus) zeigt Skala-Stufe + Hinweis „Wortlaut-Prüfung nicht verfügbar" (.kc-r-unverif); ohne Freitext unverändert. +2 Tests. 82/82 grün. npm run build nötig. |
| 2026-06-19 | Diagnose · Leerzeichen | Fehlende Leerzeichen an Wortgrenzen (Opus + gpt-5.5) als Modell-Token-Grenzen identifiziert, nicht code-seitig: kein Streaming, strtr-Normalisierung fasst keinen Whitespace an, Konsolen-Print erhält Leerzeichen (empirisch bestätigt); gpt-5.5 reproduzierte denselben verbatim-Schluss korrekt, Opus nicht — gleicher Code-Pfad. Sicherheitsnetz: kanonischerSchluss() schnappt eine KI-schluss, die bis auf Whitespace einem der vier Tier-Texte gleicht, auf den exakten Config-Text. Freitext-Felder (spiegel/luecken/gesamt-Nuance) bleiben modellseitig. +1 Test. 81/81 grün. |
| 2026-06-19 | Prompt v2 · Konsistenz | Nach erster Auswertung (User-Prompt überarbeitet, max_tokens=4096): (1) Nutzernachricht liefert pro Frage Grad (Baustein/Skalenwert/Grad/Freitext) mit. (2) Vier kanonische Stufen-Texte als config('klarheits_check.stufen') = eine Wahrheit für Prompt <gesamturteil>, Service-Fallback und JS-No-Text-Pfad (STUFEN/stufeFor); Gesamtstufe aus Anzahl „scharf"-Grade (>=4/2–3/sonst). Alte widersprüchliche Texte (Schärfe ist da / hält das) entfernt. (3) geradeAnfuehrung() normalisiert typografische → gerade Anführungszeichen nach dem Parsen (Sicherheitsnetz gpt-5.4-mini). +2 Tests (Grad in Nutzernachricht, Quote-Normalisierung). 79/79 grün. |
| 2026-06-19 | CP 5.4 · Werkzeug | Auswertung in App\Services\KlarheitsCheckAuswerter extrahiert (Controller delegiert; Verhalten unverändert, 78/78). Neues Artisan-Command klarheits-check:probe {--provider=openai} {--only=} spielt 4 Szenarien (floskeln, scharf, widerspruch, offtopic/Injection) gegen den Anbieter und zeigt das JSON — zur Ton-Kalibrierung. 3 gemockte Command-Tests. |
| 2026-06-19 | Prompt-Engineering | System-Prompt auf die kuratierte Version aus klarheits-promt.md umgestellt (XML-Tags: <haltung>/<grundsatz>/<pruefregeln>/<floskeln>/<abgleich>/<zuschreibung>/<aufgabe>/<beispiele>, Urteilsregeln je Baustein, Few-Shot). Neu: <relevanz>-Block = Themen-/Missbrauchs-Prüfung + Prompt-Injection-Schutz (Anweisungen im Freitext werden ignoriert, Prompt nie ausgegeben). JSON-Vertrag unverändert → kein Frontend-Eingriff. +1 Config-Test. 75/75 grün. |
| 2026-06-19 | Phase 4 · Privacy-Modus | KI-Anfrage im Privacy-Modus: OpenAI-Call mit store=false (keine Speicherung der Completion); Anthropic ohne Request-Flag (API-Bedingung „kein Training"). In .kc-privacy + Datenschutz-Abschnitt dokumentiert. Test prüft store=false. 74/74 grün. |
| 2026-06-19 | Phase 4 | Datenschutz: Hinweis .kc-privacy am Auswerten-Punkt (Freitext → Anthropic/OpenAI, USA, keine Speicherung, sonst lokal) + Link auf datenschutz#ki-auswertung; neue Datenschutz-Sektion „6. KI-Auswertung". 2 Tests (Check-Hinweis, Datenschutz-Abschnitt). 74/74 grün. npm run build nötig. |
| 2026-06-19 | Phase 3 · Dual-KI | OpenAI als zweiter Anbieter, umschaltbar über KLARHEITS_CHECK_KI (anthropic | openai) → config('klarheits_check.ki.provider'). openaiText() (Chat Completions, response_format: json_object, max_completion_tokens, Http::withToken) neben anthropicText(); gemeinsamer Prompt/Vertrag/Fallback. .env.example dokumentiert. +1 Test (Switch ruft OpenAI, nicht Anthropic). 72/72 grün. |