Die Pipeline liess GPT Artikel umschreiben und legte sie direkt als geplanten WordPress-Beitrag an - ohne dass ein Mensch sie gesehen hat. Der KI-Hinweis auf dem Blog sagt aber redaktionelle Pruefung zu, und genau daran haengt die Ausnahme in Art. 50 Abs. 4 KI-VO. Neuer Status `pending_review` zwischen Rewrite und Publish: Die Pipeline endet beim Rewrite, ohne WordPress-Beitrag und ohne Publish-Slot. Erst die Freigabe im Portal stempelt Pruefer und Systemzeit, reserviert den Slot und legt den Beitrag an. - Migration: editorial_review_at/_by/_note, Status-CHECK erweitert - Spalten-Migration laeuft nach den Tabellen-Neubauten erneut, sonst verwirft der aeltere no_image-Rebuild die frisch angelegten Spalten - Jeder Weg nach `approved` stempelt (Button, Statuswechsel, API) - Jeder maschinelle Rewrite loescht einen alten Stempel - Telegram: Info mit Portal-Link statt Draft-Meldung, kein Freigabe-Button - Altbestand bleibt unberuehrt und veroeffentlicht weiter - EDITORIAL_REVIEW_REQUIRED=false stellt den alten Ablauf wieder her - 14 neue Tests, docs/KI-VO.md Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
63 lines
1.9 KiB
Python
63 lines
1.9 KiB
Python
from __future__ import annotations
|
|
|
|
UI_STATUSES = ("new", "rewrite", "freigabe", "publish", "published", "close", "no_image")
|
|
|
|
# Menschenlesbare Beschriftungen fuer die Admin-UI.
|
|
UI_STATUS_LABELS: dict[str, str] = {
|
|
"new": "Neu",
|
|
"rewrite": "Rewrite",
|
|
"freigabe": "Wartet auf Freigabe",
|
|
"publish": "Freigegeben / eingeplant",
|
|
"published": "Veroeffentlicht",
|
|
"close": "Verworfen",
|
|
"no_image": "Kein Bild",
|
|
}
|
|
|
|
|
|
def internal_to_ui_status(status: str | None) -> str:
|
|
value = (status or "").strip()
|
|
if value == "approved":
|
|
return "publish"
|
|
if value == "error":
|
|
return "close"
|
|
if value == "pending_review":
|
|
return "freigabe"
|
|
if value == "review":
|
|
return "rewrite"
|
|
if value in {"new", "rewrite", "published", "no_image"}:
|
|
return value
|
|
return value or "new"
|
|
|
|
|
|
def ui_to_internal_status(status: str | None) -> str:
|
|
value = (status or "").strip()
|
|
if value == "publish":
|
|
return "approved"
|
|
if value == "close":
|
|
return "error"
|
|
if value == "freigabe":
|
|
return "pending_review"
|
|
if value in {"new", "rewrite", "published", "no_image"}:
|
|
return value
|
|
if value in {"approved", "error", "review", "pending_review"}:
|
|
return value
|
|
return value
|
|
|
|
|
|
def ui_status_label(status: str | None) -> str:
|
|
value = (status or "").strip()
|
|
return UI_STATUS_LABELS.get(value, value or "new")
|
|
|
|
|
|
# `freigabe` ist das Tor zur Veroeffentlichung: nur ueber diesen Zustand (oder
|
|
# einen bewussten manuellen Wechsel) erreicht ein Artikel `publish`, und beides
|
|
# stempelt die redaktionelle Freigabe (Art. 50 Abs. 4 KI-VO).
|
|
ALLOWED_UI_TRANSITIONS: dict[str, set[str]] = {
|
|
"new": {"rewrite", "close"},
|
|
"rewrite": {"freigabe", "publish", "close"},
|
|
"freigabe": {"publish", "rewrite", "close"},
|
|
"publish": {"published", "close"},
|
|
"published": {"rewrite", "close"},
|
|
"close": {"rewrite"},
|
|
"no_image": {"rewrite", "close"},
|
|
}
|