diff --git a/dev/issues/README.md b/dev/issues/README.md index 23bc6eb..69c3864 100644 --- a/dev/issues/README.md +++ b/dev/issues/README.md @@ -30,4 +30,9 @@ afectados y notas de implementacion. | 22a | E2E: Infraestructura base | [0022a-e2e-infra.md](completed/0022a-e2e-infra.md) | completado | | 22b | E2E: Auth fixtures y helpers | [0022b-e2e-auth-helpers.md](completed/0022b-e2e-auth-helpers.md) | completado | | 22c | E2E: Tests de agentes + docs | [0022c-e2e-agent-tests.md](completed/0022c-e2e-agent-tests.md) | completado | -| 23 | Seccion de tests en dashboard | [0023-dashboard-tests.md](completed/0023-dashboard-tests.md) | completado | +| 23 | Seccion de tests en dashboard | [0023-dashboard-tests.md](completed/0023-dashboard-tests.md) | completado | +| 24 | Grupos y permisos centralizados | [0024-centralized-security-groups.md](0024-centralized-security-groups.md) | pendiente | +| 24a | Security types: pkg/security/ | [0024a-security-types.md](0024a-security-types.md) | pendiente | +| 24b | Security loader: shell/security/ | [0024b-security-loader.md](0024b-security-loader.md) | pendiente | +| 24c | Security integration + cleanup | [0024c-security-integration.md](0024c-security-integration.md) | pendiente | +| 25 | Catálogo cron + scaffolder | [0025-cron-scaffolder.md](completed/0025-cron-scaffolder.md) | completado | diff --git a/dev/issues/completed/0025-cron-scaffolder.md b/dev/issues/completed/0025-cron-scaffolder.md new file mode 100644 index 0000000..2a7cfdd --- /dev/null +++ b/dev/issues/completed/0025-cron-scaffolder.md @@ -0,0 +1,169 @@ +# 0025 — Catálogo de automatizaciones cron + scaffolder + +## Objetivo + +Crear un directorio `crons/` como catálogo central de automatizaciones nombradas, y un conjunto de +scripts en `dev-scripts/cron/` para crear nuevas automatizaciones, listarlas y aplicarlas a agentes +sin editar YAML a mano. Evolución directa de la infraestructura creada en el issue 0005. + +## Contexto + +- `shell/cron/` ya implementa el scheduler con `send_message` y `llm_prompt` (issue 0005) +- Las automatizaciones se definen en cada `agents//config.yaml` bajo `schedules:`, lo que las + dispersa y dificulta reutilizarlas entre agentes +- No hay forma de crear una nueva automatización sin editar YAML a mano y conocer la estructura +- No existe un catálogo centralizado ni scripts de gestión +- Depende de: issue 0005 (completado) + +## Arquitectura + +``` +crons/ NEW — catálogo de automatizaciones nombradas + good-morning/ + schedule.yaml NEW — spec (description, cron, action, output_room por defecto) + prompts/ + message.md NEW — plantilla de mensaje + daily-summary/ + schedule.yaml NEW + prompts/ + prompt.md NEW + +dev-scripts/cron/ NEW — herramientas de gestión + new.sh NEW — scaffolder interactivo + list.sh NEW — listar automatizaciones con descripción + apply.sh NEW — añadir automatización a config de agente + +shell/cron/scheduler.go MODIFY — añadir Fire(name) para disparo manual en tests +shell/cron/actions.go MODIFY — pequeñas mejoras si surgen al escribir ejemplos +``` + +### Patrón pure core / impure shell + +- `pkg/` — sin cambios (no hay lógica pura nueva) +- `shell/cron/` — modificación mínima: añadir `Fire(ctx, sc)` para testing manual +- `crons/` — datos puros (YAML + Markdown), sin código Go +- `dev-scripts/cron/` — shell scripts impuros (leen/escriben filesystem, parchean YAML) + +### Convención de `crons//schedule.yaml` + +```yaml +# Metadata +name: good-morning +description: "Saludo de buenos días en una sala" + +# Schedule por defecto (el agente puede sobreescribir) +default_cron: "0 9 * * *" + +# Acción +action: + kind: send_message # send_message | llm_prompt + template: prompts/message.md # relativo a la carpeta de la automatización + +# Sala por defecto (opcional; el agente puede sobreescribir con output_room) +default_output_room: "" +``` + +Este archivo es solo **documentación + template**. El agente lo referencia en su `config.yaml` +usando la sección `schedules:` habitual; `apply.sh` automatiza ese paso. + +## Tareas + +### Fase 1: Estructura `crons/` y automatizaciones de ejemplo + +- [ ] **1.1** Crear `crons/` con un `README.md` que explique la convención +- [ ] **1.2** Crear `crons/good-morning/schedule.yaml` + `prompts/message.md` (ejemplo `send_message`) +- [ ] **1.3** Crear `crons/daily-summary/schedule.yaml` + `prompts/prompt.md` (ejemplo `llm_prompt`) + +### Fase 2: Scripts de gestión en `dev-scripts/cron/` + +- [ ] **2.1** `dev-scripts/cron/new.sh` — scaffolder interactivo: + - Pregunta: nombre, descripción, tipo (`send_message` o `llm_prompt`), cron expression + - Crea `crons//schedule.yaml` y el archivo de prompt/mensaje vacío + - Imprime el bloque YAML listo para copiar en `config.yaml` +- [ ] **2.2** `dev-scripts/cron/list.sh` — lista todas las carpetas bajo `crons/` con nombre y + descripción extraída del `schedule.yaml` +- [ ] **2.3** `dev-scripts/cron/apply.sh ` — añade la entrada `schedules:` a + `agents//config.yaml` con los valores por defecto del `schedule.yaml`. Usa `yq` si está + disponible; en caso contrario imprime el bloque YAML para copiar a mano + +### Fase 3: Mejora menor en `shell/cron/` + +- [ ] **3.1** Exportar `Fire(ctx context.Context, sc config.ScheduleCfg)` en `scheduler.go` para + poder disparar un schedule en tests o desde CLI sin esperar al cron +- [ ] **3.2** Actualizar `scheduler_test.go` para usar `Fire` en lugar de `@every 100ms` donde + sea posible (reduce tiempo de test) + +### Fase 4: Tests + +- [ ] **4.1** Test de `Fire` para `send_message` inline +- [ ] **4.2** Test de `Fire` para `llm_prompt` +- [ ] **4.3** Verificar que `go test -tags goolm ./shell/cron/...` pasa sin regresiones + +### Fase 5: Cleanup y docs + +- [ ] **5.1** Añadir entrada `crons/` en la tabla de estructura de `CLAUDE.md` +- [ ] **5.2** Añadir `dev-scripts/cron/` en la misma tabla +- [ ] **5.3** Mención en `dev-scripts/agent/README.md` o crear `dev-scripts/cron/README.md` + +--- + +## Ejemplo de uso + +```bash +# Crear una nueva automatización +./dev-scripts/cron/new.sh + +# → Nombre de la automatización: weekly-report +# → Descripción: Resumen semanal del equipo +# → Tipo de acción [send_message/llm_prompt]: llm_prompt +# → Cron expression [default: 0 9 * * 1]: 0 9 * * 1 +# ✓ Creado: crons/weekly-report/schedule.yaml +# ✓ Creado: crons/weekly-report/prompts/prompt.md +# +# Añade esto a agents//config.yaml: +# schedules: +# - name: weekly-report +# cron: "0 9 * * 1" +# output_room: "!ROOM:server.com" +# action: +# kind: llm_prompt +# template: "crons/weekly-report/prompts/prompt.md" + +# Listar automatizaciones disponibles +./dev-scripts/cron/list.sh + +# → good-morning send_message "0 9 * * *" Saludo de buenos días +# → daily-summary llm_prompt "0 18 * * *" Resumen diario del equipo +# → weekly-report llm_prompt "0 9 * * 1" Resumen semanal del equipo + +# Aplicar a un agente (parchea config.yaml automáticamente) +./dev-scripts/cron/apply.sh good-morning assistant-bot +# → Añadido schedule 'good-morning' a agents/assistant-bot/config.yaml +# → Edita output_room en config.yaml para apuntar a la sala correcta +``` + +## Decisiones de diseño + +- **`crons/` como catálogo de datos, no de código**: Los archivos `schedule.yaml` son solo + documentación + template. No hay un registry Go nuevo; el scheduler sigue leyendo de + `config.yaml` como hasta ahora. Esto evita añadir un pattern nuevo al proyecto. +- **`apply.sh` opcional**: Si `yq` no está disponible, el script imprime el bloque YAML para + copiar a mano. Sin dependencias obligatorias. +- **`Fire()` en lugar de cron real en tests**: Los tests actuales usan `@every 100ms` y duermen + 350ms. `Fire()` los hace deterministas e instantáneos. +- **No registry Go para crons**: Añadir un registry compilado (como `cmd/launcher`) para crons + sería over-engineering. La gestión vía shell scripts es suficiente y más flexible. + +## Prerequisitos + +- Issue 0005 completado (scheduler en `shell/cron/` — ya está) + +## Riesgos + +- **`yq` no disponible en el entorno**: `apply.sh` cae back a imprimir el bloque YAML, nunca + falla. Sin riesgo real. +- **Paths relativos en `schedule.yaml`**: El campo `template` en el YAML es relativo a la raíz + del proyecto. Documentar claramente en el `README.md` del catálogo. +- **Divergencia entre catálogo y config del agente**: Si alguien edita `schedule.yaml` después + de aplicarlo, el agente no se actualiza. Es intencional — `apply.sh` es un helper de + scaffolding, no sync continua.