001-progress-tracker/spec.md

SPEC-001 — Progress tracker (GitLab → resumen para X)

SPEC-001 — Progress tracker (GitLab → resumen para X)

Id: projects/001-progress-tracker/spec
Estado: borrador — especificación de producto; implementación pendiente.


Objetivo

Entregar una herramienta pequeña (prioridad: script Node.js en el repo; alternativa aceptable: mini-web local o ruta Astro solo-dev) que, con configuración mínima, obtenga el último commit del proyecto en GitLab y genere un resumen visual (texto enriquecido o ASCII/Unicode “card”) listo para copiar y pegar en Twitter / X, alineado con la voz técnica del blog (Synthcode / Neo-Dev).


Requisitos funcionales (MVP)

  1. Mensaje del commit — título (primera línea) y, si aplica, cuerpo truncado o segunda línea según límite de caracteres acordado para la red.
  2. Fecha del commit — en hora local del usuario o UTC explícita; formato legible en una sola línea (p. ej. ISO corto + zona).
  3. Enlace al repositorio — URL canónica del proyecto en GitLab (no solo al commit, salvo que se documente un modo “enlace al SHA”; el MVP exige al menos repo visible en el bloque generado).

Salida

  • Bloque de texto copiable de un clic (CLI imprime a stdout y opcionalmente copia al portapapeles si la plataforma lo permite).
  • URL de Twitter/X Web Intent (twitter.com/intent/tweet?text=...) con el texto codificado (encodeURIComponent), enlace al sitio (https://caprini.dev por defecto o /blog/[slug] vía env) y apertura opcional del navegador con la librería open; TWITTER_INTENT_NO_OPEN=1 desactiva la apertura. Detalle: episodio 020.
  • Estilo “visual”: bordes Unicode, separadores o mini-banner en monospace; debe verse bien en feed y en capturas.

Fuentes de datos

  • GitLab REST API o GraphQL (decisión en implementación): lectura del último commit de la rama por defecto o de una rama configurable (main por defecto, acorde a AGENT_PERSISTENT_MEMORY.md).
  • Configuración: variables de entorno (p. ej. GITLAB_TOKEN con scope read_api / read_repository según necesidad), GITLAB_PROJECT_ID o path with namespace (caprini/caprini-blog). No commitear secretos.

No objetivos (MVP)

  • Publicación automática vía API oficial de X (sin OAuth ni envío servidor a servidor); el flujo vigente es asistido: Intent + revisión humana en el compositor.
  • Historial completo o comparativas entre commits.

Módulo de Generación Visual

Alcance: extensión de SPEC-001 para Fase 2 — además del bloque de texto copiable, la herramienta debe poder materializar una tarjeta gráfica coherente con la marca del sitio.

Objetivo

Producir un archivo PNG de 1200×675 píxeles (formato de imagen recomendado para enlaces / preview en Twitter / X) que incluya, como mínimo:

  1. Logo del Carpincho-Tech — asset canónico según src/content/docs/system/BRANDING.md (p. ej. public/assets/images/logo-flat.png o logo-circle.png; la implementación fijará cuál usar en tarjeta y documentará la ruta).
  2. Mensaje del commit — al menos la primera línea (título); si el diseño lo admite, cuerpo truncado con elipsis.
  3. Fecha del commit — misma fuente de verdad que el tracker (GitLab); formato legible en el lienzo (una o dos líneas máximo para no competir con el título).

Estética (normativa)

La composición debe seguir src/content/docs/system/BRANDING.md:

  • Fondo oscuro dominante alineado al token bg-void (#0d1117), no sustituido por grises “claros” de mood distinto.
  • Bordes y/o acentos neón (cian y/o púrpura en el rango definido en BRANDING), usados con puntualidad — marco de tarjeta, separadores o glow discreto, sin saturar el lienzo.
  • Tipografía: JetBrains Mono (o equivalente monospace acordado y documentado en el PR de implementación), coherente con el resto del producto Neo-Dev / Synthcode.

Investigación técnica (decisión cerrada)

EnfoqueIdeaProsContras / notas
node-canvasAPI Canvas 2D en Node (canvas): dibujo imperativo (rectángulos, texto, drawImage del logo).Control fino, un solo binario PNG al final; patrón familiar para quien viene de gráficos por código.Dependencias nativas en algunos entornos (compilación / CI); maquetar layout complejo puede ser más lento que en CSS.
Satori (Vercel)Convierte HTML + CSS (subset limitado pero expresivo) a SVG; el PNG se obtiene rasterizando ese SVG (p. ej. @resvg/resvg-js).Alineado con layout declarativo; iteración visual paralela al sitio Astro.Subset de CSS/HTML: validar fuentes embebidas, bordes y sombras según documentación de Satori; cadena SVG→PNG a mantener.

Implementación vigente: Satori + @resvg/resvg-js en projects/001-progress-tracker/tracker.mjs — función generateCard(commit); salida en public/assets/images/latest.png (ruta fija para la Home) y public/assets/images/last-progress-card.png (alias). Opcional: PROGRESS_CARD_SNAPSHOT=1 genera además progress-card-<ISO>.png. Fuente JetBrains Mono (.ttf) en projects/001-progress-tracker/assets/fonts/ (requerida en tiempo de ejecución).

Condición de parada (generación visual)

Sin archivo de fuente JetBrains Mono en la ruta acordada, el generador no debe continuar con rasterizado opaco: el mensaje de error debe indicar la ruta esperada. node-canvas permanece como alternativa documentada si en el futuro se priorizan deps nativas ya resueltas en CI.

Criterios de aceptación (módulo visual — cuando se implemente)

  • Salida PNG 1200×675 estable y reproducible desde los mismos datos que alimentan el resumen textual (mismo commit / misma ejecución del tracker o subcomando documentado).
  • Composición verificable frente a BRANDING (fondo void, neón puntual, JetBrains Mono).
  • Ruta de salida y comando documentados (sin secretos); fallos (fuente faltante, asset ausente) con mensaje claro.

Criterios de aceptación

  • Con credenciales válidas y proyecto existente, el comando (o la mini-web) produce en menos de unos segundos un bloque que incluye mensaje, fecha y enlace al repo.
  • Fallos de red o 401/404: mensaje de error claro en stderr, código de salida distinto de cero en CLI.
  • Documentar en un párrafo en AGENT_PERSISTENT_MEMORY.md o runbook corto dónde vive el script y qué env vars usar (sin valores secretos).

Implementación sugerida (para la siguiente iteración)

  • Ubicación: scripts/gitlab-last-commit-summary.mjs (o nombre equivalente), type: module, fetch nativo.
  • Tests: pruebas con mocks de respuesta GitLab (sin red en CI) para el formateador del bloque final.
  • Opcional: página Astro solo en dev que llame a un endpoint local — solo si aporta UX clara frente al script.

Referencias

  • Proyecto habitual: GitLab caprini/caprini-blog, rama main (memoria persistente del agente).
  • Episodio de contexto: src/content/docs/system/episodes/004-limpieza-y-primera-spec.md.