- Decision-Update Preisstruktur & Veroeffentlichungs-Flow aufgenommen (Launch-Tarife, Slot-Verbrauch bei Veroeffentlichung, Submit-Gate, Launch-Credits) inkl. Klarstellung 12.06.: Gelb geht direkt live, keine manuelle Pruef-Queue, nur Rot wird abgelehnt - Alle Status-Dokumente auf den Code-Stand gezogen: README-Index, STATUS-ABGLEICH (KI-Pipeline, Bilder/Lizenzen, Pricing), Checkliste (KI- und Titelbild-Bloecke, Launch-To-dos), Admin-User, user-zusammenhaenge (Datenmodell-Delta), Entwicklungsplan KI-Pruefung (Phase 0 abgehakt, Decision-Abgleich) - Ueberschriebene Tarif-Abschnitte in Konzept-Update 1/2 und Relaunch-Konzept mit Superseded-/IST-Hinweisen markiert - Neues Plan-Dokument PHASE-9-FLOW-UND-TARIFE-PLAN.md (9A-9J) - Phase-8-Roadmap-Doku (20-PHASE-8-USER-PANEL.md) + PROGRESS-Eintraege Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
26 KiB
Entwicklungsplan: KI-Prüfung & Veröffentlichungs-Pipeline
Stand: 11.06.2026 — Phasen 0–5 abgeschlossen, Phase 6 (Trust-Score) offen.
Dieser Plan definiert die schrittweise Umsetzung der automatisierten Prüfung und Veröffentlichung von Pressemitteilungen (PM). Er ist so geschnitten, dass jede Phase einzeln umgesetzt, getestet und ausgeliefert werden kann.
Abgleich mit dem Decision-Update (11.06.2026): Das
Decision-Update Preisstruktur & Veröffentlichungs-Flowsetzt auf dieser Pipeline auf und ergänzt zum Launch drei noch offene Flow-Regeln, die nicht Teil dieses Plans waren:
- Submit-Gate: „Zur Prüfung einreichen" wird hinter eine aktive Buchung gelegt (das Modal zeigt ohne Buchung einen Buchungs-Hinweis).
- Slot-Verbrauch bei Veröffentlichung statt bei Einreichung — rot abgelehnte PMs verbrauchen keinen Slot. Der aktuelle Quota-Stub zählt noch beim Einreichen (
submitForReview) und muss umgestellt werden.- Kein Re-Check zum Launch: eine Einreichung = eine Prüfung; Nachbessern + erneut prüfen kommt erst in Phase 2.
- Gelb-Routing geändert (Entscheidung 12.06.2026): Gelb geht zum Launch direkt live wie Grün — keine manuelle Review-Queue mehr. Nur Rot wird abgelehnt (mit Begründung an den Autor). Phase 4 unten beschreibt das ursprünglich gebaute Verhalten (Gelb → manuelle Queue); die Umstellung erfolgt im Phase-9-Plan (
docs/PHASE-9-FLOW-UND-TARIFE-PLAN.md, Päckchen 9A).
Ziel & Leitprinzip
Jede eingehende PM wird automatisch von einer KI geprüft. Nur in äußersten Fällen erfolgt eine manuelle redaktionelle Prüfung. Zwei Einreichungsstellen müssen denselben Prüf-Pfad durchlaufen:
- Web-Formular (Customer- und Admin-Editor)
- API (
/api/v1/press-releases)
Es gibt zwei voneinander unabhängige Bewertungen (Konzept-Update 1, Abschnitt 15):
- Klassifikations-Score (Grün/Gelb/Rot) — der „Red Flag": entscheidet, ob überhaupt veröffentlicht wird. Jetzt umzusetzen.
- Content-Score (0–100) → Stufe (Standard/Geprüft/Hochwertig) — die Qualitätsbewertung („Scoring"). Spätere Phase.
Konzept-Grundlage
docs/konzept/Konzept-Update 1 – Überarbeitete Abschnitte.md, §15.1 (Klassifikations-Score) und §15.2 (Content-Score).docs/konzept/Konzept-Update 2 – Score-Stufen-System.md(Stufen-Mapping,content_tier, Außenkommunikation).
Klassifikations-Score laut Konzept §15.1:
| Klassifikation | Bedeutung | Auswirkung |
|---|---|---|
| Grün | unauffällig | direkte Veröffentlichung (optional 5–10 Min. Verzögerung) |
| Gelb | unklar/grenzwertig | manuelle Review-Queue (nicht boostbar) |
| Rot | unzulässig | zurück an Autor mit Begründung, keine Veröffentlichung |
Faktoren (Red Flags): Werbung statt PM, beleidigend/diskriminierend, rechtlich
heikel, Spam-Muster, unseriöse Versprechen. Speicherung laut Konzept:
press_releases.classification plus Audit-Log ki_audits.
Ist-Zustand (Bestandsaufnahme)
- Statuswerte (
App\Enums\PressReleaseStatus):draft,review,published,rejected,archived. - Web-Einreichung:
App\Services\PressRelease\PressReleaseService::submitForReview()prüft nur eine wortbasierte Blacklist (config/blacklist.phpviaBlacklistService), setzt sonst Statusreview, erhöht das Quota und schreibt einPressReleaseStatusLog. - Veröffentlichung:
PressReleaseService::publish()(Admin-Aktion) und der CronApp\Console\Commands\PublishScheduledPressReleases(publiziertreview-PMs mit fälligemscheduled_at). Beide prüfen erneut nur die Blacklist. - API:
App\Http\Controllers\Api\V1\PressReleaseController::store()/update()schreibenstatusdirekt aus dem Request (erlaubt:draft,review) und rufensubmitForReviewnicht auf. Eine API-PM mitstatus=reviewlandet damit ohne Blacklist-/Quota-/Log-Prüfung in der Queue. - UI-Einreichung (Prozess-Start):
- Detailansicht ([show.blade.php]): vollständiges Modal
confirm-submit-reviewmit rechtlichen Hinweisen, Quota-Anzeige und Bestätigungs-Checkboxen → ruftsubmitForReview. - Bearbeiten ([edit.blade.php]): Button „Speichern & zur Prüfung" mit nur
wire:confirm(Browser-Dialog), kein Modal. - Erstellen ([create.blade.php]): Button „Zur Prüfung senden" ohne Modal.
- Detailansicht ([show.blade.php]): vollständiges Modal
- Kein Datenmodell für Klassifikation/Score: keine Spalten
classification,content_score,content_tier, keine Tabelleki_audits.
Lücken & Risiken
- L1 — API-Bypass: Einreichung über die API umgeht jede Prüfung.
- L2 — Keine echte Inhaltsprüfung: nur eine triviale Wort-Blacklist; keine Erkennung von Werbung, Spam, rechtlich heiklen oder unseriösen Inhalten.
- L3 — Auto-Publish ohne Klassifikation: geplante PMs werden vom Cron veröffentlicht, ohne dass eine inhaltliche Bewertung stattgefunden hat.
- L4 — Uneinheitlicher Prozess-Start: das Bestätigungs-Modal existiert nur in der Detailansicht, nicht beim Bearbeiten/Erstellen.
- L5 — Kein Audit: KI-Entscheidungen wären ohne
ki_auditsnicht nachvollziehbar (DSGVO / Nachweispflicht).
Zielarchitektur
Einreichung (Formular ODER API)
│
▼
SubmissionService.submit() ← ein einziger Funnel
│
├─ Hard-Filter: Blacklist (synchron, deterministisch)
▼
ClassificationService.classify() ← KI (Claude), mit Fallback
│
├─ Rot → status=rejected, Begründung an Autor
├─ Gelb → status=review (manuelle Queue, „äußerste Fälle")
└─ Grün → Veröffentlichungspfad (sofort / geplant)
│
▼
ki_audits (vollständiges Audit-Log jeder KI-Entscheidung)
+
press_releases.classification / classified_at
+
(später) content_score / content_tier
Kernregeln:
- Formular und API rufen ausschließlich
SubmissionService.submit()auf. Die API darfstatusnicht mehr frei setzen;publishedist über die API nie erreichbar. - Re-Klassifikation bei jeder Änderung einer PM (Konzept §15.1: „Bei Änderung der PM wird neu klassifiziert").
- Schwellen/Verhalten sind konfigurierbar (
config/scoring.php), damit sie ohne Code-Änderung kalibriert werden können.
Entwicklungsschritte
Phase 0 — Prozess-Start im UI vereinheitlichen — ✅ erledigt (11.06.2026)
Ziel: Das bestehende Einreichungs-Modal erscheint überall dort, wo eine PM eingereicht wird — auch beim Bearbeiten (Button „Speichern & zur Prüfung") und beim Erstellen (Button „Zur Prüfung senden"). Reiner UI-Schritt, kein Backend.
Umsetzung: Das Modal confirm-submit-review (rechtliche Hinweise, Quota,
Bestätigungs-Checkboxen) wird in Customer-Show, -Create und -Edit über
flux:modal.trigger geöffnet; bestätigt ruft es wie geplant
submitForReview bzw. saveAndSubmit/save('review').
Umfang:
- Modal
confirm-submit-reviewausshow.blade.phpin eine wiederverwendbare Blade-/Volt-Komponente extrahieren (z. B.resources/views/livewire/components/press-release-submit-modal.blade.php). - In
edit.blade.phpdenwire:confirm-Button durch einenflux:modal.triggerersetzen; bei Bestätigung wird wie bishersaveAndSubmitausgeführt (erst speichern, dann einreichen). - In
create.blade.phpdenselben Modal-Trigger vorsave('review')schalten. - Texte/Checkboxen identisch zur Detailansicht halten (rechtliche Hinweise, Quota, Bestätigungen).
Betroffene Dateien: resources/views/livewire/customer/press-releases/{show,edit,create}.blade.php,
neue Komponente unter resources/views/livewire/components/.
Done: In allen drei Ansichten (Customer: show/edit/create) öffnet derselbe Bestätigungsdialog; Tests für Edit/Create-Submit grün.
Admin-Editor (/admin/press-releases/) — bewusst ausgenommen: Der
Admin-Editor behält sein bisheriges Verhalten (wire:confirm). Begründung: Wenn
eine PM beim Admin landet, hat die vorgelagerte User-Prüfung (Einreichungs-Modal
im Customer-Flow) bereits stattgefunden. Der Admin braucht hier keinen erneuten
Bestätigungsdialog. Stattdessen erhält der Admin-Editor in einer späteren Phase
einen zusätzlichen „Prüfung"-Button (siehe Phase 4: On-Demand-KI-Prüfung).
Tests: Volt-Tests, die das Öffnen des Modals und den Submit-Pfad
(saveAndSubmit / save('review')) abdecken.
Phase 1 — Einreichungs-Funnel & API-Absicherung — ✅ erledigt (11.06.2026)
Ziel: Beide Einreichungsstellen laufen durch einen Pfad; die API-Lücke (L1) wird geschlossen. Noch ohne KI — nur Vereinheitlichung.
Umsetzung:
PressReleaseService::submitForReview()ist der alleinige Einreichungs-Einstieg (Web-Formular und API rufen dieselbe Methode). Auf eine separateSubmissionService-Fassade wurde bewusst verzichtet —submitForReviewist bereits die stabile Schnittstelle, in die Phase 3 die KI-Klassifikation einhängt.- API:
statusaus den Validierungsregeln vonStorePressReleaseRequestundUpdatePressReleaseRequestentfernt (inkl. ungenutzter Imports).store()erzeugt jetzt immerPressReleaseStatus::Draft; ein übergebenesstatuswird ignoriert.update()kann den Status nicht mehr setzen. - Neue explizite Route
POST /api/v1/press-releases/{pressRelease}/submit(press-releases.submit) →PressReleaseController::submit(). Diese prüftpress-releases:write, Ownership und erlaubt nurdraft/rejected(sonst 409); ruftsubmitForReview(); eineBlacklistViolationExceptionwird als 422 mit Begründung zurückgegeben. Damit greifen Blacklist-, Quota- und Status-Log-Behandlung auch für API-Einreichungen. publishedist über die API weiterhin nie erreichbar (nur Admin-Aktion/Cron).
Betroffene Dateien: app/Http/Controllers/Api/V1/PressReleaseController.php,
app/Http/Requests/Api/V1/{Store,Update}PressReleaseRequest.php,
routes/api.php. PressReleaseService blieb unverändert (Schnittstelle
ausreichend).
Done: API kann keine PM mehr ungeprüft in review heben; eine PM-Einreichung
verhält sich über API und Formular identisch.
Tests: tests/Feature/Api/V1/PressReleaseSubmitApiTest.php (Create erzeugt
immer Draft & ignoriert status; Submit-Route hebt nach review, zählt Quota,
schreibt Log; Blacklist → 422 + rejected; fehlende Schreibrechte → 403;
bereits in review → 409; fremde PM → 403). Alle grün.
Phase 2 — Datenmodell & Audit — ✅ erledigt (11.06.2026)
Ziel: Persistenz für Klassifikation und vollständiges KI-Audit. Noch ohne Verhaltensänderung (alle Felder nullable).
Umsetzung:
- Migration
add_classification_to_press_releases: Spaltenclassification(string(16), nullable, nachstatus) undclassified_at(timestamp, nullable) plus Index aufclassification.content_score/content_tierbewusst erst in Phase 5 (siehe Datenmodell-Anhang). - Migration
create_ki_audits_table:press_release_id(FK, cascade),type,provider(nullable),model(nullable),result(nullable),reason(text, nullable),raw_response(json, nullable),created_at(useCurrent), Index(press_release_id, type). Keinupdated_at(append-only Log). - Model
App\Models\KiAudit($timestamps = false, Castraw_response→ array, KonstantenTYPE_CLASSIFICATION/TYPE_CONTENT_SCORE, RelationpressRelease()), RelationPressRelease::kiAudits()(neueste zuerst). - Enum
App\Enums\PressReleaseClassification(Green/Yellow/Red +label()), inPressRelease::casts()fürclassificationregistriert. config/scoring.php: Anbieter/Modell-Auswahl (CLASSIFICATION_PROVIDER, Defaultdeterministic,CLASSIFICATION_MODEL), Timeout, Grün-Verzögerung (Minuten), Gelb→manuelle-Queue-Flag sowie Content-Score-Stufen-Schwellen (Phase 5).KiAuditFactorymit Statesclassification()/contentScore().
Betroffene Dateien: zwei neue Migrationen unter database/migrations/,
app/Models/PressRelease.php, app/Models/KiAudit.php,
app/Enums/PressReleaseClassification.php, config/scoring.php,
database/factories/KiAuditFactory.php.
Done: Migrationen laufen; Modelle/Casts/Relation vorhanden; keine bestehende Funktionalität verändert (alle Felder nullable).
Tests: tests/Feature/PressReleaseClassificationModelTest.php (Enum-/
Datetime-Cast, Default null, kiAudits()-Reihenfolge, raw_response-Array-Cast
- Relation, Cascade-Delete). Alle grün.
Phase 3 — KI-Klassifikation (Red Flag) — ✅ erledigt (11.06.2026)
Ziel: Echte inhaltliche Prüfung jeder Einreichung; Ergebnis asynchron als Klassifikation gespeichert und auditiert.
Entscheidungen (11.06.2026): Erster aktiver Anbieter ist OpenAI (Key/ Budget vorhanden); Anthropic/Gemini folgen über dieselbe Treiber-Schnittstelle. Klassifikation läuft asynchron über die Queue (synchron wäre später nicht handelbar). Zum Testen ohne Dauer-Worker gibt es einen Drain-Befehl.
Umsetzung:
- Provider-agnostische Treiber-Architektur unter
app/Services/PressRelease/Classification/:- Interface
Contracts\ClassificationDriver::classify(PressRelease): ClassificationResult. ClassificationResult(Value Object: Enum-Klassifikation,reasons[],provider,model,rawResponse,reasonText()).Drivers\OpenAiClassificationDriver— OpenAI Chat-Completions viaHttp-Client, liestconfig/services.openai(Key/URL/Modell/Timeout), erzwingtresponse_format: json_objectund parst{classification, reasons[]}. Wirft bei fehlendem Key / HTTP-Fehler / ungültigem JSON.Drivers\DeterministicClassificationDriver— Blacklist → Rot/Grün (nie Gelb), als Fallback ohne externe API.ClassificationManager(Laravel-Manager) löst den Treiber ausconfig('scoring.classification.provider')auf (createOpenaiDriver/createDeterministicDriver).
- Interface
- Asynchroner Job
app/Jobs/ClassifyPressRelease(Queueclassification,tries=3): klassifiziert über den aktiven Treiber, bei Ausfall Fallback auf den deterministischen Treiber (mitLog::warning), schreibtpress_releases.classification/classified_atund einenki_audits-Eintrag (inkl.provider/model/reason/raw_response). - Einbindung in den Funnel:
PressReleaseService::submitForReview()stößt nach dem synchronen Blacklist-Hard-Filter und dem Statuswechsel den Job an (ClassifyPressRelease::dispatch(...)->onQueue('classification')). Greift für Formular und API (gemeinsamer Einstieg aus Phase 1). - Drain-Befehl
php artisan classification:work(Option--once): arbeitet die Queue einmalig ab und beendet sich (queue:work --stop-when-empty) — zum Testen ohne permanenten Worker. - Konfig:
config/scoring.phpDefault-Provider aufopenaigesetzt (CLASSIFICATION_PROVIDER); Modell leer ⇒config('services.openai.model'). - Test-Isolation:
phpunit.xmlerzwingtCLASSIFICATION_PROVIDER=deterministicund leerenOPENAI_API_KEY, damit die Suite keine echten OpenAI-Calls macht; der OpenAI-Pfad wird gezielt mitHttp::fake()getestet.
Noch offen (bewusst): Re-Klassifikation bei jeder PM-Änderung (Update über Formular/API) ist noch nicht verdrahtet — Phase 3 klassifiziert beim Einreichen. Nachzuziehen, wenn das Status-Routing (Phase 4) steht. Anthropic-/ Gemini-Treiber + SDK folgen separat.
Betroffene Dateien: app/Services/PressRelease/Classification/*,
app/Jobs/ClassifyPressRelease.php,
app/Console/Commands/RunClassificationQueue.php,
app/Services/PressRelease/PressReleaseService.php, config/scoring.php,
phpunit.xml.
Done: Jede Einreichung (Formular + API) stößt asynchron eine Klassifikation
an, erzeugt einen ki_audits-Eintrag; bei KI-Ausfall greift der deterministische
Fallback nachvollziehbar. Status-Routing folgt in Phase 4.
Tests: tests/Feature/PressReleaseClassificationJobTest.php (OpenAI grün/gelb
mit Http::fake, Fallback bei HTTP-500, deterministisch Rot bei Blacklist,
Dispatch auf Queue classification via Queue::fake). Alle grün; volle Suite
416 grün (2 vorbestehende WIP-Failures unverändert).
Phase 4 — Routing, Auto-Publish & Review-Queue — ✅ erledigt (11.06.2026)
Ziel: Die Klassifikation steuert den Status. Manuelle Prüfung nur noch bei Gelb.
Umsetzung:
- Routing im Job über
PressReleaseService::routeByClassification()(vomClassifyPressRelease-Job nach dem Klassifizieren aufgerufen):- Rot →
reject(..., source: 'ki'):status=rejected, KI-Begründung per Mail an den Autor (PressReleaseRejected, wie bei Blacklist). - Gelb → keine Aktion, bleibt
review(manuelle Admin-Queue). - Grün →
autoPublishGreen(): ohne Termin sofort veröffentlichen, optional mit Sicherheitsfensterscoring.classification.green_delay_minutes(überpublished_at-Override); mit zukünftigemscheduled_atbleibt die PM inreviewund der Scheduler publiziert zum Termin. - Greift nur, solange die PM noch
reviewist (manuelle Admin-Eingriffe haben Vorrang).publish()erhielt einen?Carbon $publishedAtOverride-Parameter,reject()einenstring $source-Parameter.
- Rot →
- Scheduler
PublishScheduledPressReleases: Kandidaten-Query umwhere('classification', 'green')erweitert — nur grüne fällige PMs werden automatisch publiziert; gelbe warten immer auf den Admin. Geplante Termine werden weiterhin respektiert. - Admin-Review-Queue: Index- und Show-Ansicht zeigen ein KI-Klassifikations-
Badge (grün/gelb/rot); der Index hat einen Klassifikations-Filter
(
classificationFilter, inkl. URL-Param, Active-Chip, Reset) — damit „nur Gelb" filterbar. Die Show-Ansicht blendet im Review-Block den KI-Hinweis (Begründung aus dem jüngstenki_audits-Eintrag) ein.
Test-Isolation (wichtig): Da Tests mit sync-Queue den Job inline ausführen,
wurde der Klassifikations-Job in den „submit→review"-Tests via Queue::fake()
entkoppelt (Workflow, PublishModal, API-Submit). Die Scheduler-Tests setzen jetzt
classification = green für Publish-Kandidaten; neuer Test: fällige gelbe PM
bleibt review.
Betroffene Dateien: app/Services/PressRelease/PressReleaseService.php,
app/Jobs/ClassifyPressRelease.php,
app/Console/Commands/PublishScheduledPressReleases.php, Admin-Views
resources/views/livewire/admin/press-releases/{index,show}.blade.php.
Done: Grüne PMs gehen automatisch live (sofort/zum Termin), rote werden abgelehnt + Autor benachrichtigt, nur gelbe landen in der manuellen Queue; Admin sieht Klassifikation + KI-Begründung und kann nach Gelb filtern.
Tests: Routing in PressReleaseClassificationJobTest (Rot→rejected+Mail,
Grün-sofort→published+Mail, Grün-geplant→bleibt review, Gelb→bleibt review);
Scheduler in PressReleaseSchedulingTest (grün fällig→published, gelb
fällig→review); Admin-UI in PressReleaseIndexPhase8bTest (KI-Badge,
Klassifikations-Filter). Volle Suite 423 grün (2 vorbestehende WIP-Failures).
Admin „Prüfung"-Button (On-Demand-KI-Prüfung) — ✅ erledigt (11.06.2026):
- Im Admin-Editor gibt es oben den Button „Prüfung", der ein Modal
admin-ki-checköffnet: auswählbare Klassifikation (Content-Score als „in Vorbereitung" deaktiviert) und ein Anbieter-Override (Konfiguriert / OpenAI / Deterministisch). runKiCheck()dispatchtClassifyPressReleaseauf der Queueclassificationmitroute: falseund optionalemproviderOverride. Das ist eine nachgelagerte Re-Check-Prüfung: sie aktualisiert nurclassification+ki_audits, ohne den Status zu ändern (kein Auto-Publish/Reject) — die Entscheidung bleibt beim Admin (Ergebnis sichtbar in der Detailansicht).- Dafür erhielt
ClassifyPressReleasedie Parameterbool $route = trueund?string $providerOverride = null.
Tests: tests/Feature/Admin/AdminKiCheckTest.php (Button/Modal sichtbar;
Dispatch mit route=false + Provider-Override; Abbruch ohne Auswahl;
Re-Check-Job aktualisiert Bewertung, lässt Status unverändert).
Re-Klassifikation bei Änderung (Konzept §15.1) — ✅ erledigt (11.06.2026):
- Neue Service-Methode
reclassifyIfClassified(): dispatcht – nur wenn die PM bereits klassifiziert ist –ClassifyPressReleasemitroute: false(Re-Check ohne Statusänderung). - Eingehängt überall dort, wo Inhalt geändert wird, und nur bei tatsächlicher
Änderung von Titel/Text (
wasChanged(['title', 'text'])): Customer-Editorsave(), Admin-Editorsave(), APIupdate(). Beim Einreichen übernimmt weiterhinsubmitForReviewdie (routende) Klassifikation.
Tests: tests/Feature/PressReleaseReclassifyTest.php (Service dispatcht nur
bei vorhandener Klassifikation; API-Update klassifiziert neu bei Text-Änderung,
nicht bei reiner Keyword-Änderung).
Noch offen / Folgearbeiten:
- Live-Aktualisierung der Ansicht nach Abschluss des Hintergrund-Jobs (Polling/Event) wäre ein optionales UX-Upgrade; aktuell erscheint das Ergebnis nach Reload/Navigation.
- Content-Score-Option im Prüfungs-Modal — ✅ mit Phase 5 aktiviert (s. u.).
Phase 5 — Content-Score & Stufen — ✅ erledigt (11.06.2026)
Ziel: Qualitätsbewertung 0–100 → Stufe Standard/Geprüft/Hochwertig (Konzept-Update 2).
Umsetzung:
- Datenmodell: Migration
add_content_score_to_press_releases—content_score(tinyint, nullable),content_tier(string, nullable, Index),scored_at. EnumApp\Enums\PressReleaseContentTier(Standard/Geprueft/Hochwertig) mitfromScore()(Schwellen ausconfig/scoring.php),label()undisPubliclyBadged()(Standard wird laut Update 2 nicht beworben). InPressReleaseals Cast registriert. - Schwellen (
config/scoring.php): Geprüft ≥ 60, Hochwertig ≥ 80 (Update 2), kalibrierbar; plus Anbieter/Modell/Timeout für den Score. - Treiber-Architektur unter
app/Services/PressRelease/ContentScore/analog zur Klassifikation:Contracts\ContentScoreDriver,ContentScoreResult,Drivers\OpenAiContentScoreDriver(gewichtete Faktoren §15.2 als JSON{score, breakdown}),Drivers\DeterministicContentScoreDriver(regelbasierte Heuristik: Länge, Bild, Quelle, Headline, Vollständigkeit),ContentScoreManager. - Job
app/Jobs/ScorePressRelease(Queueclassification, Fallback auf deterministisch): schreibtcontent_score+ abgeleitetecontent_tier+scored_atundki_audits(type=content_score). OptionalerproviderOverride. - Berechnung bei Einreichung (
submitForReviewdispatcht Klassifikation und Score) und bei Inhaltsänderung (rescoreIfScored()in Customer-/ Admin-Editor und API-update(), analog zur Re-Klassifikation). - Anzeige:
- Customer-Editor: Score-Panel (Punktzahl, Stufe, „noch X Punkte bis zur nächsten Stufe") — der produktive Editor-Score laut Update 2.
- Admin-Index & -Show: Stufen-/Score-Badge (intern inkl. Punktzahl).
- Customer-Detailansicht: öffentliches Stufen-Badge (✓ Geprüft / ★ Hochwertig; Standard ohne Badge).
- Admin-Prüfungs-Modal: Content-Score-Option aktiviert;
runKiCheck()dispatcht zusätzlichScorePressRelease.
Done: Score wird bei Einreichung/Änderung berechnet, Stufe abgeleitet, auditiert und überall sichtbar.
Tests: tests/Feature/PressReleaseContentScoreTest.php (Tier-Mapping,
öffentliche Badges, OpenAI-Score→Tier+Audit, Fallback, Dispatch bei Submit,
Re-Score nur wenn bereits bewertet); Editor-Panel in
CustomerPressReleaseEditPhase7Test; Stufen-Badge in PressReleaseIndexPhase8bTest;
Content-Score-Dispatch in AdminKiCheckTest. Volle Suite 440 grün.
Noch offen / Folgearbeiten:
- Public Web-Frontend (presseecho/businessportal24): Stufen-Badges in den öffentlichen Listen/Detailseiten gemäß Update 2 ergänzen (bisher nur im Portal/Backend und der Customer-Ansicht).
- Score-History & Breakdown-Ansicht (Publisher-Dashboard) und Boost- Eligibilität (Abschnitt 16) sind eigene spätere Ausbaustufen.
Phase 6 — Trust-Score (später)
Account-/Firmen-Ebene (Konzept §15.3): lockert die KI-Freigabe-Schwelle für zuverlässige Publisher. Eigene spätere Ausbaustufe; hier nur als Ausblick vermerkt.
Datenmodell-Anhang (Zielzustand)
press_releases (Ergänzungen)
+ classification enum(green,yellow,red) NULL
+ classified_at timestamp NULL
+ content_score tinyint NULL (Phase 5)
+ content_tier enum(standard,gepruft,hochwertig) NULL (Phase 5)
ki_audits (neu)
- id
- press_release_id FK
- type enum(classification,content_score)
- provider string (z. B. anthropic)
- model string (z. B. claude-opus-4-8)
- result string/json
- reason text NULL
- raw_response json/longtext
- created_at timestamp
Offene Entscheidungen
- Anbieter & Modell — ✅ entschieden (11.06.2026): Erster aktiver Anbieter
ist OpenAI (
CLASSIFICATION_PROVIDER=openai, Modell ausconfig/services.openai). Architektur provider-agnostisch; Anthropic/Gemini folgen. Offen bleibt, ob später mehrere Anbieter parallel (Primär + Fallback jenseits des deterministischen) laufen sollen. - Synchron vs. Queue — ✅ entschieden (11.06.2026): Queue (asynchron,
Queue-Name
classification). Drain zum Testen:php artisan classification:work. - Dependency: OpenAI-Treiber nutzt den nativen
Http-Client (kein neues Composer-Paket). Anthropic PHP-SDK (anthropic-ai/sdk) ist freigegeben; für Gemini je ein offizielles/etabliertes SDK oder HTTP-Client bei Umsetzung des Treibers. - Grün-Verzögerung: 0 Min. (sofort) oder 5–10 Min. (Konzept-Option) als
Sicherheitsfenster — konfigurierbar über
scoring.classification.green_delay_minutes, Default noch festzulegen. - Gelb-Verhalten: ausschließlich manuelle Queue, oder zusätzlich automatische Benachrichtigung des Autors.
- DSGVO: Aufbewahrung/Anonymisierung der
raw_responseinki_audits.
Nächste Schritte
Phasen 0–5 sind umgesetzt (Suite grün). Es folgen:
- Launch-Block aus dem Decision-Update (siehe Abgleich-Box oben): Submit-Gate hinter Buchung, Slot-Verbrauch bei Veröffentlichung, Tarif-/Zahlungs-Modul.
- Betrieb: Queue-Worker für
classificationim Produktions-Setup (Test-Drain:php artisan classification:work). - Folgearbeiten: Live-Aktualisierung des KI-Ergebnisses in der UI, Stufen-Badges im öffentlichen Web-Frontend, Anthropic-/Gemini-Treiber.
- Phase 6: Trust-Score (eigene Ausbaustufe).