7b92079c41830c8fafd8cae5094b6b7195fc10c9
Los waivers se indexaban SOLO por slug. Hoy no hay colisiones (los slugs ES van en español), pero nada lo impedía: un slug repetido entre blogs habría aplicado en silencio la excepción del sitio equivocado, y ese post habría dejado de auditarse sin que nadie se enterara. Riesgo latente, no activo — pero 'no pasa hoy' no es lo mismo que 'no puede pasar'. EXCEPTIONS[site][familia][slug] = razón accepted_reason(rule, slug, site='en') El default 'en' mantiene funcionando a seo_audit.py sin tocarlo (es EN-only). seo_watch y seo_finish pasan el sitio activo explícitamente. Añadido collisions(): lista los slugs waiveados en más de un sitio. Debe estar siempre vacío; si algo aparece ahí, hay una excepción ambigua que revisar. Verificado: mismo slug waiveado en EN se audita con normalidad en ES; los 16 waivers EN intactos; seo_audit, seo_watch (ambos sitios) y seo_finish (ambos sitios) siguen dando los mismos resultados que antes del cambio. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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%