0844b7596ece1205f62315b84343697cdb4de009
Faltaba la pieza de ESCRITURA en el cuerpo. El resto de herramientas leen `html`, que Ghost renderiza venga de donde venga, y por eso el formato les da igual; para escribir hay que tocar la fuente, y la fuente viene en tres sabores: lexical con un bloque html los 29 del ES y casi todo el EN lexical con nodos nativos roswell-341 y yellow-sea (extended-text) mobiledoc con tarjetas html lo que genera ResearchOwl HOY en los borradores El tercero se descubrió el 2026-07-21 con el Canarias de prueba: los scripts que veníamos usando asumían lexical y habrían abortado sobre el próximo artículo recién generado. Las salvaguardas son cicatrices de errores reales de estos días: destino en el corpus del sitio correcto, aviso si el destino está programado (enlace prematuro → 404 en la ventana), URL con el canónico de cada sitio (EN www, ES apex), el anchor nunca dentro de un <a> existente, y comprobación de anclas balanceadas y no anidadas antes de escribir. Sin --apply no toca nada. Probado en los tres formatos. El de mobiledoc, de punta a punta contra Ghost con un borrador de usar y tirar: Ghost acepta la escritura, renderiza el enlace, el mobiledoc sigue siendo válido y el texto queda intacto (2.143 palabras antes y después). Borrador borrado tras la prueba. Lo que la herramienta NO hace es decidir: en la prueba encontró «Roswell» dentro de «Roswell Daily Record», que sería un anchor pésimo. Elegir el anchor sigue siendo humano.
seo-tools
SEO rule engine + tooling for the Ghost blogs (EN: theexclusionzone.com).
seo_rules.py— shared rule engine (pure functions, no I/O). Single source of truth for thresholds + checks. Consumed by the auditor, the validator, and (vendored) by ResearchOwl's blog pipeline.seo_audit.py— Tool A: site-wide auditor (reads all published posts viaghst-en).seo_validate.py— Tool C: single-post pre-publish validator (seo-checkwraps this).seo_exceptions.py— documented, consciously-accepted waivers (auditor reporting filter).seo_mirror.py— OG/Twitter mirroring helper.phase2_*.py/json— one-off batch helpers (kept for provenance).
No secrets live here. Ghost access is via the ghst-en wrapper (~/.local/bin), which
fetches a staff token on demand from the pod and never writes it to disk.
Languages
Python
100%