Twitter Digest

# Como Funciona Todo, Fase por Fase

Esta pagina explica el flujo completo del Twitter Digest sin asumir conocimiento tecnico. Para cada fase vas a encontrar: que hace conceptualmente, que recibe y que produce, cuando se ejecuta, quien lo ejecuta, y por que existe.

## Estado Actual de Automatizacion

Hoy: nada se ejecuta solo. Tu arrancas cada fase manualmente con un comando. El sistema puede automatizarse con cron (Phase 7), pero eso aun no esta configurado.

Modo Manual (hoy)

Tu corres los scripts uno por uno. Util para probar, entender, y validar que todo funcione antes de automatizar.

Modo Automatico (futuro)

Cuando configures Phase 7, el servidor ejecuta todo por horario: scrapea 3 veces al dia y genera el digest a las 10pm sin intervencion.

## Glosario

Gate: una condicion que tiene que cumplirse para poder continuar. Si el gate no pasa, todo el pipeline se detiene. Es un punto de control de calidad.

Slot: un momento del dia en el que se scrapea Twitter. Hay 3 slots: morning (8am), midday (1pm), evening (6pm).

Agente AI: un modelo de inteligencia artificial (Claude o z-ai) que ejecuta una tarea especifica siguiendo un contrato estricto. No improvisa — sigue reglas escritas.

Contrato (CLAUDE.md): un documento que le dice al agente AI exactamente que puede hacer, que no puede tocar, que formato usar, y cuando parar. Es como un manual de instrucciones rigido.

Artifact: un archivo de salida que prueba que una fase se completo. Ejemplo: `published.ok` confirma que el digest del dia se publico.

Pipeline: el flujo completo de principio a fin. Cada fase alimenta a la siguiente, como una linea de ensamblaje.

## El Dia Completo, de un Vistazo

Asi se ve un dia tipico cuando todo esta automatizado:

8:00
Scrape morning — Primera recoleccion de tweets del feed "For You"
8:10
Procesar + Captions — Separar tweets, descargar imagenes, generar descripciones AI
13:00
Scrape midday — Segunda recoleccion (el feed ya roto, hay tweets nuevos)
13:10
Procesar + Captions — Misma rutina, acumula al archivo del dia
18:00
Scrape evening — Tercera y ultima recoleccion del dia
18:10
Procesar + Captions — Ultimo procesamiento. Al final, todas las imagenes estan descritas.
22:00
Digest final — El orquestador genera el resumen del dia, renderiza la pagina web, envia Telegram, y marca el dia como publicado.

Phase 1

## Ingest — Recoleccion de Tweets

Esta fase se encarga de recolectar tweets del feed "For You" de Twitter y organizarlos en archivos estructurados. No hay inteligencia artificial aqui — son scripts que abren tu timeline, hacen scroll, y guardan lo que encuentran. Se ejecuta 3 veces al dia para capturar la mayor cantidad de contenido posible.

Por que se scrapea 3 veces al dia y no 1?

El feed "For You" de Twitter rota constantemente. Los tweets que te muestra a las 8am no son los mismos que a la 1pm o a las 6pm. Si solo scrapeas una vez, te pierdes la mayoria del contenido. Con 3 pasadas (morning, midday, evening) capturas una muestra mucho mas representativa de lo que Twitter considero relevante para tu cuenta a lo largo de todo el dia.

Pieza 1 de 2

El Scraper — Recolector de tweets crudos

Cuando corre: 3 veces al dia — 8:00 AM (morning), 1:00 PM (midday), 6:00 PM (evening).

Que recibe: El nombre del slot (morning, midday, o evening) y la fecha del dia. Tambien necesita las cookies de sesion de tu cuenta de Twitter (@maurosicard) para autenticarse — es como si el script "abriera" Twitter logueado con tu cuenta.

Que hace: Abre tu timeline "For You" y hace 6 rondas de scroll, capturando ~20 tweets por ronda. Entre cada ronda espera 30 a 60 segundos al azar para simular comportamiento humano y no ser bloqueado por Twitter. De cada tweet extrae: texto, autor, likes, retweets, replies, URLs de imagenes, si tiene video, y fecha de publicacion.

Cuantos tweets: Cada pasada captura aproximadamente ~120 tweets brutos (6 rondas x 20). Con 3 pasadas al dia son ~360 brutos. Despues de eliminar duplicados (tweets que aparecen en mas de una pasada), el archivo final del dia tiene tipicamente entre 100 y 200 tweets unicos.

Que produce: Dos cosas:

- Un archivo individual de esa pasada (ej: `0800_morning.csv`) — como un "recibo" de lo que se capturo en ese momento.
- Un archivo acumulado del dia (`raw_feed.csv`) — fusiona todas las pasadas del dia eliminando duplicados. Este archivo crece con cada pasada.

Pieza 2 de 2

El Procesador — Organizador y descargador de imagenes

Cuando corre: Inmediatamente despues de cada scrape — ~8:10 AM, ~1:10 PM, ~6:10 PM.

Que recibe: El archivo acumulado del dia (`raw_feed.csv`) con todos los tweets recolectados hasta ese momento.

Que hace: Lee cada tweet y toma una decision simple: tiene imagen o no? Los separa en dos archivos distintos. Para los tweets que tienen imagen, descarga cada foto fisicamente al servidor desde los servidores de Twitter (pbs.twimg.com). Un tweet puede tener hasta 4 imagenes. Tambien marca los tweets que tienen video (pero no descarga el video, solo lo anota).

Detalle importante: Este script es seguro de correr multiples veces. Si ya descargo una imagen antes, no la descarga de nuevo. Si un tweet ya tenia una descripcion de imagen (de Phase 2), la preserva. Esto permite que corra despues de cada pasada sin perder trabajo previo.

Que produce: 4 cosas:

- Tweets sin imagen (`no_images.csv`) — ~55% de los tweets tipicamente. Incluye una nota si el tweet tiene video.
- Tweets con imagen (`with_images.csv`) — ~45% de los tweets. Incluye los nombres de las imagenes descargadas y un campo vacio para la descripcion (que llenara Phase 2).
- Carpeta de imagenes (`images/`) — Las fotos descargadas. En un dia tipico hay entre 25-50 imagenes. Nombres tipo: `levelsio-tweetid-2006097888-image1.jpg`.
- Inventario (`manifest.json`) — Un listado estructurado de todas las imagenes: cuantas hay, de que tweets vienen, cuales se descargaron exitosamente.

Por que hay 2 scripts separados y no 1 solo?

Porque hacen cosas distintas en momentos distintos. El scraper solo recolecta datos de Twitter — es rapido y depende de la conexion a internet. El procesador organiza esos datos localmente — descarga imagenes, separa archivos, genera inventarios. Separarlos permite, por ejemplo, correr el procesador sin volver a scrapear, o re-procesar datos si algo fallo en la descarga de imagenes.

Ejemplo real (31 dic 2025):

- 35 tweets unicos en el feed del dia
- 19 tweets sin imagen (fueron a `no_images.csv`)
- 16 tweets con imagen (fueron a `with_images.csv`)
- 28 imagenes descargadas en total (algunos tweets tenian 2-4 fotos)
- 48 archivos en la carpeta `images/`
- Contenido: tech (AI, Claude Code), finanzas (ETFs), gaming (Tekken, PlayStation), ofertas, y contenido viral

Phase 2

## Captions — Descripciones de Imagenes + Gate de Calidad

Esta fase toma todas las imagenes descargadas en Phase 1 y le pide a un agente de inteligencia artificial que las mire una por una y escriba una descripcion en texto. Esto es necesario porque el digest final es un resumen escrito — sin estas descripciones, el agente que genera el digest no sabria que hay en las fotos. Ademas, esta fase tiene un gate: un punto de control que bloquea todo el pipeline hasta que todas las imagenes esten descritas.

Por que hace falta describir las imagenes?

El agente AI que genera el digest (Phase 3/5) necesita entender que hay en cada imagen para decidir si un tweet es relevante y como presentarlo. Por ejemplo, un tweet puede decir "This is insane" con una captura de pantalla de un benchmark de AI — sin la descripcion, el agente no sabria que el tweet es sobre AI performance. Las descripciones son literales (2-5 oraciones): que se ve, que texto hay visible, que numeros si hay graficos.

Pieza 1 de 3

El Loop de Captioning — Ciclo autonomo hasta completar

Cuando corre: Despues de cada procesamiento — ~8:10 AM, ~1:10 PM, ~6:10 PM (inmediatamente despues del procesador de Phase 1).

Que recibe: La fecha del dia. Internamente busca el inventario de imagenes (`manifest.json`) y el archivo de tweets con imagen (`with_images.csv`) de esa fecha.

Que hace: Ejecuta un ciclo repetitivo con 3 pasos:

1. Llamar al agente AI (z-ai) — Le pasa las imagenes que faltan por describir. El agente las mira y escribe descripciones. Cada intento tiene un limite de 20 minutos.
2. Aplicar descripciones — Toma las descripciones generadas y las inserta en el archivo de tweets con imagen.
3. Validar — Revisa si todas las imagenes del inventario ya tienen descripcion.

Si la validacion pasa, crea el archivo `images_done.ok` (el gate) y termina. Si faltan descripciones, espera 30 segundos y vuelve a intentar el ciclo. Repite indefinidamente hasta que todo este completo o se detenga manualmente.

Que produce: El archivo gate `images_done.ok` — la prueba de que todas las imagenes del dia tienen descripcion.

Pieza 2 de 3

El Agente AI de Imagenes — z-ai con contrato estricto

Quien es: Un modelo de AI (z-ai) que puede ver imagenes. Recibe un contrato escrito (`CLAUDE.md`) que le dice exactamente que hacer y que no hacer.

Que puede hacer: Leer imagenes, leer el inventario y las descripciones existentes, y solo escribir nuevas descripciones al final del archivo de descripciones. No puede modificar ningun CSV, no puede borrar descripciones anteriores, no puede acceder a internet.

Como describe: Para cada imagen, escribe una descripcion literal de 2-5 oraciones. Si la imagen tiene texto visible (capturas de pantalla, graficos), lo cita tal cual. Si tiene numeros o datos (benchmarks, tablas), los incluye. Nunca inventa contenido que no sea visible en la imagen.

Si falla: En vez de saltarse la imagen, escribe un registro de error (`CAPTION_FAILED: razon`) para que el sistema sepa que esa imagen necesita otro intento.

Pieza 3 de 3

El Validador — Control de calidad final

Que hace: Compara el inventario de imagenes (`manifest.json`) contra las descripciones generadas. Responde una pregunta simple: cada imagen del inventario tiene una descripcion valida?

Resultados posibles:

- Todo OK — Todas las imagenes tienen descripcion. El loop crea `images_done.ok` y termina.
- Incompleto — Faltan descripciones. El loop vuelve a intentar.
- Error critico — Algo esta roto (archivos corruptos, formato invalido). El pipeline se detiene.

El Gate: `images_done.ok`

Este archivo es el punto de control mas importante del pipeline. Si no existe, nada de lo que sigue puede ejecutarse: no se genera digest, no se publica pagina, no se envia notificacion. Existe para garantizar que el digest nunca se publique con imagenes sin describir, lo cual haria que el agente de digest trabaje con informacion incompleta.

Phase 3

## Digest Contract — Las Reglas del Resumen

Esta fase no ejecuta nada. Es un documento de reglas (`CLAUDE.md`) que el agente AI de Phase 5 lee antes de generar el digest. Piensa en esto como el "manual de estilo" que define como se seleccionan los tweets, como se organizan, que formato tiene el JSON de salida, y que pasa si algo falla. Es la fase mas conceptual de todas — puro contrato, cero codigo ejecutable.

Concepto 1 de 3

Reglas de Seleccion — Como se eligen los tweets del digest

De los ~100-200 tweets recolectados en Phase 1, el agente tiene que elegir los mejores para el digest. El proceso es determinista (siempre da el mismo resultado con los mismos datos):

1. Eliminar tweets invalidos — Los que no tienen ID, URL, o contenido se descartan.
2. Eliminar duplicados — Si un tweet aparecio mas de una vez, se queda solo con la primera aparicion.
3. Aplicar exclusiones globales — Se eliminan tweets sobre temas prohibidos: crypto, dating, fitness, drama politico, motivational fluff, etc. (definidos en `INTEREST.md`).
4. Aplicar minimos de likes — Cada categoria de interes tiene un umbral minimo. Ejemplo: tips de Claude Code necesitan al menos 50 likes, discusiones de AI necesitan 100+, pero noticias oficiales no tienen minimo.
5. Rankear por likes — Los tweets restantes se ordenan de mayor a menor likes. En caso de empate, gana el tweet mas reciente.
6. Distribuir en secciones — Los mejores tweets se agrupan en 3-5 secciones tematicas.

Si quedan menos de 3 tweets elegibles despues del filtrado, el agente declara fallo. No genera un digest medio vacio — prefiere no publicar nada.

Concepto 2 de 3

Tus Intereses — El archivo `INTEREST.md`

Este archivo le dice al agente que temas te importan y cuales ignorar. Es tu perfil de preferencias. Hoy incluye 5 categorias de interes:

- Claude Code & AI Agents — Workflows, MCP servers, agentic coding. Min 50 likes para tips, 0 para noticias.
- AI & LLMs — Nuevos modelos, benchmarks, tecnicas. Min 100 likes para discusiones, 0 para anuncios oficiales.
- GenAI / Image & Video — Workflows practicos de generacion de imagenes/video. Min 50 likes.
- Apps & Developer Tools — macOS apps, CLI tools, self-hosted. Prioridad: self-hosted > one-time > subscription.
- Automation — n8n, Shortcuts, browser automation, scripting.

Detalle interesante: La pagina web del digest (Phase 4) tiene un formulario de feedback. Si al leer tu digest envias una sugerencia ("quiero mas contenido de X" o "deja de mostrarme Y"), esa sugerencia se agrega automaticamente a este archivo. El proximo digest ya toma en cuenta tu feedback.

Concepto 3 de 3

Estructura del Digest — Que forma tiene el resultado

El contrato define una estructura rigida para el `digest.json`:

- Titulo del dia — Un titulo editorial para el digest.
- 3-5 secciones tematicas — Cada una con icono, titulo, y tags.
- Bloques narrativos — Parrafos escritos por el agente que dan contexto y conectan los tweets.
- Bloques de tweets — Los tweets seleccionados con todos sus datos + un campo `why` que explica en 1-2 oraciones por que ese tweet fue elegido.
- Cierre editorial — Un parrafo de despedida.

Cada seccion tiene que tener al menos un bloque narrativo y un bloque de tweet. El agente tambien genera un checkpoint (`digest_checkpoint.md`) que es un reporte de status: que archivos leyo, que tweets selecciono, si hubo problemas, si el resultado es valido.

Continuidad con dias anteriores

El agente lee los ultimos 7 digests anteriores antes de generar uno nuevo. Esto le permite evitar repetir tweets que ya se cubrieron, mantener coherencia narrativa, y notar tendencias que se han desarrollado a lo largo de la semana.

3 modos de operacion

- CREATE — No existe digest para esa fecha. Genera desde cero.
- MODIFY — Ya existe un digest y tu das instrucciones especificas de que cambiar (ej: "quita el tweet X", "agrega una seccion de gaming").
- REGENERATE — Ya existe un digest pero quieres que lo rehaga completo desde cero.

Phase 4

## Render — La Pagina Web del Digest

Esta fase tampoco ejecuta nada por si sola. Contiene el template (plantilla) que convierte el `digest.json` en una pagina web navegable. Es un archivo PHP que lee el JSON y lo renderiza como HTML con estilos, tipografia, y embeds de tweets. El orquestador (Phase 5) se encarga de copiarlo al lugar correcto.

Pieza 1 de 2

El Template PHP — Maquina de renderizado

Que es: Un archivo PHP (`index.php.template`) que actua como plantilla universal. No es especifico de ninguna fecha — funciona para cualquier dia. Cuando se ejecuta, busca el archivo `digest.json` que esta en la misma carpeta y lo convierte en una pagina web completa.

Que muestra: El titulo del dia, cada seccion con sus narrativas y tweets, el cierre editorial, y un formulario de feedback al final. Los tweets se muestran con el contenido, nombre, username, likes, retweets, replies, y el campo `why` que explica por que se eligio.

Como se despliega: El orquestador (Phase 5) copia este template a la carpeta del dia como `index.php`. Al acceder a esa URL en el navegador, PHP lo ejecuta, lee el `digest.json` de la misma carpeta, y renderiza la pagina.

Pieza 2 de 2

El Loop de Feedback — Aprendizaje continuo

Que es: La pagina web del digest tiene un formulario al final donde puedes escribir sugerencias en texto libre: "quiero ver mas contenido de Rust", "deja de mostrar gaming", etc.

Que pasa al enviar: Tu sugerencia se agrega automaticamente al archivo `INTEREST.md` (Phase 3) con la fecha y hora. La proxima vez que se genere un digest, el agente AI leera esas sugerencias y las tomara en cuenta para la seleccion y presentacion de tweets.

El ciclo: Lees el digest → envias feedback → el proximo digest se adapta → repites. Esto permite que el digest evolucione con tus intereses sin tener que editar archivos manualmente.

Frontend assets

Ademas del template PHP, hay una carpeta `twitter-app/` con los recursos visuales: CSS, JavaScript, las fuentes tipograficas de Twitter (Chirp Bold, Medium, Regular), y el logo de Twitter en SVG. Esto hace que el digest se vea como si fuera parte de Twitter.

Phase 5

## Orchestrator — El Director de Orquesta

Esta es la fase central. Un unico script que ejecuta todo el pipeline de punta a punta para una fecha: verifica datos, corre captions si faltan, valida el gate, invoca al agente AI para generar el digest, copia el template web, envia la notificacion de Telegram, y marca el dia como publicado. Es el unico script que necesitas correr si quieres hacer todo en un solo comando.

Script unico

run_digest.sh — El comando que lo hace todo

Cuando corre: Una vez al dia, tipicamente a las 10:00 PM, despues de que las 3 pasadas de scraping y captioning ya terminaron.

Que recibe: Solo la fecha (`YYYY-MM-DD`). Todo lo demas lo busca automaticamente en las carpetas del pipeline.

Que hace, paso a paso:

1. Verifica datos crudos — Si no existe `raw_feed.csv`, intenta fusionar las pasadas individuales. Si no hay nada, falla.
2. Corre el procesador (Phase 1) — Asegura que los tweets esten separados y las imagenes descargadas.
3. Corre captions (Phase 2) — Asegura que todas las imagenes tengan descripcion.
4. Verifica el gate — Si `images_done.ok` no existe despues de intentar captions, falla y se detiene.
5. Invoca al agente AI (Claude) — Le pasa el contrato de Phase 3 y los datos del dia. Claude genera `digest.json` y `digest_checkpoint.md`.
6. Valida el digest — Verifica que el JSON sea valido y que los archivos existan.
7. Copia el template web — Copia `index.php.template` (Phase 4) a la carpeta del dia como `index.php`.
8. Ajusta permisos — Asegura que los archivos sean legibles por el servidor web.
9. Envia notificacion Telegram (Phase 6) — Envia un mensaje con el link del digest.
10. Registra el dia — Agrega la fecha a `COMPLETED-DAYS.md` (ledger de dias publicados).
11. Marca como publicado — Crea `published.ok` como prueba de que todo termino bien.

Outputs finales

Lo que queda al final del dia

Al completarse exitosamente, la carpeta del dia contiene:

- `digest.json` — El resumen estructurado con todos los tweets seleccionados, narrativas, y metadata.
- `digest_checkpoint.md` — Reporte de status: que leyo, que selecciono, si hubo problemas.
- `index.php` — La pagina web lista para ver en el navegador.
- `published.ok` — Archivo que confirma publicacion exitosa.

Y a nivel global:

- `COMPLETED-DAYS.md` — Lista de todas las fechas publicadas, una por linea. Funciona como historial.

Proteccion contra ejecuciones simultaneas

El script usa un file lock: si intentas correrlo dos veces para la misma fecha al mismo tiempo, la segunda ejecucion se detiene inmediatamente en vez de competir con la primera. Esto previene archivos corruptos o duplicados.

Phase 6

## Notifications — Aviso por Telegram

Fase simple: te envia un mensaje de Telegram cuando el digest del dia esta listo. No genera contenido — solo avisa. Antes de enviar, verifica que todo este en orden: que el digest JSON exista y sea valido, que la pagina web exista, y que el gate de imagenes haya pasado.

Script unico

notify_telegram.sh — El mensajero

Cuando corre: Automaticamente al final de Phase 5 (~10pm). Tambien puede correrse manualmente.

Que verifica antes de enviar:

- Que `digest.json` exista y sea JSON valido
- Que `index.php` exista (la pagina web esta lista)
- Que `images_done.ok` exista (todas las imagenes fueron descritas)

Que envia: Un mensaje HTML a tu chat de Telegram con la fecha y el link directo a la pagina del digest. Asi puedes abrirlo desde el telefono y leer tu resumen diario en el momento que quieras.

Que necesita: 3 variables de entorno configuradas en el servidor:

- `TELEGRAM_BOT_TOKEN` — El token de tu bot de Telegram.
- `TELEGRAM_CHAT_ID` — El ID del chat donde quieres recibir el mensaje.
- `PUBLIC_BASE_URL` — La URL base de tu servidor (ej: `https://tudominio.com/twitter-digest`).

Si algo falla: El script verifica que la API de Telegram responda con `ok: true`. Si no, reporta el error. El pipeline ya se completo — el digest esta publicado independientemente de si Telegram funciono o no.

Phase 7

## Schedule — Automatizacion por Horario

Esta fase todavia no esta implementada. Es el plan para que todo lo anterior se ejecute automaticamente por horario usando cron (el scheduler del servidor Linux). Cuando se configure, no tendras que correr nada manualmente — el servidor lo hara todo solo, todos los dias.

Plan futuro

Los horarios que se configurarian

Recoleccion (Phase 1):

- 8:00 AM — Scrape morning + procesar
- 1:00 PM — Scrape midday + procesar
- 6:00 PM — Scrape evening + procesar

Captioning (Phase 2):

- 8:10 AM — Caption imagenes del scrape de las 8
- 1:10 PM — Caption imagenes del scrape de la 1
- 6:10 PM — Caption imagenes del scrape de las 6

Publicacion (Phase 5 → 6):

- 10:00 PM — Correr el orquestador completo. Genera digest, publica, envia Telegram.

Registros

Logs — Donde ver que paso cada dia

Cuando cron corra los scripts automaticamente, cada ejecucion dejara un archivo de log para poder revisar que paso si algo falla:

- Logs de scraping — Cuantos tweets se capturaron, errores de conexion, rate limits.
- Logs de procesamiento — Cuantas imagenes se descargaron, errores de descarga.
- Logs de captioning — Cuantas imagenes se describieron, intentos necesarios, timeouts.
- Logs de digest — Si el agente genero el JSON correctamente, errores de validacion.

Cuando activar esta fase?

Solo despues de que todo lo anterior funcione de forma estable manualmente. El orden recomendado es: probar Phase 1 sola, luego Phase 2, luego Phase 5, luego Phase 6, y recien cuando todo eso pase sin errores de forma consistente, configurar los cron jobs aqui.

## Orden de Prueba Recomendado

Si quieres probar el sistema desde cero, este es el orden mas seguro:

1. Solo Phase 1 — Corre un scrape y process para una fecha. Confirma que existen los CSVs, las imagenes, y el manifest.
2. Phase 2 — Corre captions hasta que se cree `images_done.ok`. Verifica que todas las imagenes tengan descripcion.
3. Phase 5 — Corre el orquestador completo. Verifica que se genere `digest.json`, `index.php`, y `published.ok`.
4. Phase 6 — Configura las variables de Telegram y confirma que llega el mensaje.
5. Phase 7 — Recien cuando todo lo anterior pase estable y repetidamente, configura los cron jobs.