b0d5e1bd0c14882c02e887c0c25d2fe49f718fb0
El check nuevo detecta encabezados en Title Case inglés, que en español no se usa. Solo corre sobre el ES (en el EN es lo correcto). Umbral de 2 palabras sospechosas por encabezado: con 1 sola, un nombre propio que falte en las listas daría un falso positivo. Verificado en los dos sentidos — 0 avisos sobre los 271 encabezados del ES ya limpios, 208 sobre el corpus de ayer, 0 sobre el corpus EN. Hace falta porque la fuga es intermitente: el 2026-07-21 había 219 encabezados sucios en 23 de 29 posts, pero otros del mismo mes salieron limpios, así que no basta con limpiar una vez. Y de paso, un agujero que apareció leyendo el código para meter el check: internal_urls() tenía theexclusionzone.com escrito a fuego. Desde que el vigilante se extendió al ES (ayer), los checks de enlaces rotos, no canónicos y prematuros buscaban en el corpus español un dominio que no aparece en él — o sea, veían 0 enlaces y no podían fallar nunca. Ahora el dominio sale de R.SITE_HOST, como el resto. Nada más arreglarlo encontró su primer hallazgo real: los-villares enlazaba a www.zonadeexclusion.com, y en el ES el canónico es el apex (al revés que en el EN). Salto 301 evitable, ya corregido en Ghost.
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%