fix(ghost): find_draft_by_title compara títulos normalizados, no igualdad exacta
Si Ghost normaliza el título al guardar (trunca a 255 un H1 largo del LLM, colapsa whitespace), la igualdad exacta no encontraba el draft recién creado y la recuperación fallaba justo en el escenario que debe cubrir. _norm_title aplica el mismo colapso+truncado a ambos lados de la comparación. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
634f38e016
commit
b58a3ce118
@@ -385,6 +385,14 @@ def _seo_dryrun_message(ghost: "GhostPublisher", post: dict, seo: dict, inserted
|
||||
)
|
||||
|
||||
|
||||
def _norm_title(t: str) -> str:
|
||||
"""Normaliza un título para compararlo con lo que Ghost almacenó: colapsa
|
||||
whitespace y trunca a 255 chars (límite de posts.title en Ghost — un H1
|
||||
largo del LLM puede volver truncado/normalizado, y la igualdad exacta
|
||||
fallaría justo en los casos que el guard debe cubrir)."""
|
||||
return " ".join((t or "").split())[:255]
|
||||
|
||||
|
||||
def _parse_ghost_ts(ts: str) -> float | None:
|
||||
"""created_at de la Admin API (ISO 8601, p.ej. 2026-07-04T20:26:00.000+00:00
|
||||
o sufijo Z) → epoch. None si no parsea."""
|
||||
@@ -438,7 +446,9 @@ class GhostPublisher:
|
||||
(p.ej. decode roto), el draft existe aunque el caller viera una
|
||||
excepción. Con `since` (epoch) solo casan drafts creados en este
|
||||
intento — un draft viejo del mismo título de una run anterior NO cuenta
|
||||
como "ya publicado". Best-effort: None si no hay match o si falla."""
|
||||
como "ya publicado". La comparación usa _norm_title (whitespace
|
||||
colapsado + truncado a 255) para sobrevivir la normalización de Ghost.
|
||||
Best-effort: None si no hay match o si falla."""
|
||||
import aiohttp as _aio
|
||||
token = self._make_token()
|
||||
url = (
|
||||
@@ -458,8 +468,9 @@ class GhostPublisher:
|
||||
if resp.status != 200:
|
||||
return None
|
||||
data = await resp.json()
|
||||
wanted = _norm_title(title)
|
||||
for p in data.get("posts", []):
|
||||
if p.get("title") != title:
|
||||
if _norm_title(p.get("title") or "") != wanted:
|
||||
continue
|
||||
if since is not None:
|
||||
created = _parse_ghost_ts(p.get("created_at") or "")
|
||||
|
||||
Reference in New Issue
Block a user