Build & Deploy ResearchOwl / build-and-push (push) Successful in 9s
Añade /generate short_en y /short_spec. El pipeline genera un shot spec con Haiku, verifica cada cifra, fecha y cita contra los chunks de la sesión, lo renderiza en shortsmith y entrega el MP4 por Telegram junto a un informe de claims. - ShortsmithClient con sondeo y fallback al spec JSON si el render falla - Contrato de plantillas obtenido de GET /templates, no codificado - Comprobación de fundamento determinista, sin LLM - outputs.published_url para enlazar el artículo de Ghost - Normalización de comillas rectas a tipográficas (ver KNOWN-ISSUES.md) Lo que no aparece en los chunks se contrasta contra el ejemplo del prompt: si casa ahí es fuga, no invención, y se informa como tal. El purgado de sesiones se lleva también su MP4. La subida a YouTube queda fuera a propósito: fase 3. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
36 lines
1.4 KiB
Python
36 lines
1.4 KiB
Python
"""Separación de capas.
|
|
|
|
`bot/` puede importar de todo; nadie puede importar de `bot/`. El progreso y
|
|
los callbacks viajan como callables genéricos justo para no necesitarlo.
|
|
"""
|
|
import re
|
|
from pathlib import Path
|
|
|
|
SRC = Path(__file__).resolve().parents[1] / "src"
|
|
LOWER_LAYERS = ("generator", "scraper", "processor", "db", "seo", "news")
|
|
|
|
IMPORTS_BOT = re.compile(r"^\s*(from\s+src\.bot|import\s+src\.bot|from\s+\.\.bot)",
|
|
re.MULTILINE)
|
|
|
|
|
|
def test_no_lower_layer_imports_from_bot():
|
|
offenders = []
|
|
for layer in LOWER_LAYERS:
|
|
for path in (SRC / layer).rglob("*.py"):
|
|
if IMPORTS_BOT.search(path.read_text(encoding="utf-8")):
|
|
offenders.append(str(path.relative_to(SRC.parent)))
|
|
assert not offenders, f"importan de bot/: {offenders}"
|
|
|
|
|
|
IMPORTS_TELEGRAM = re.compile(r"^\s*(from\s+telegram|import\s+telegram)", re.MULTILINE)
|
|
|
|
|
|
def test_the_short_pipeline_takes_progress_as_a_plain_callable():
|
|
"""La comprobación concreta para lo añadido en fase 2: si algún día alguien
|
|
mete un `Message` de Telegram aquí, este test lo dice. Nombrar Telegram en
|
|
un comentario vale — importarlo, no."""
|
|
for module in ("short.py", "shortsmith.py", "shortspec.py", "grounding.py",
|
|
"spec_contract.py"):
|
|
source = (SRC / "generator" / module).read_text(encoding="utf-8")
|
|
assert not IMPORTS_TELEGRAM.search(source), f"{module} importa telegram"
|