73f7ebb9f5
Mover a completed/ y actualizar estado en README.
170 lines
7.1 KiB
Markdown
170 lines
7.1 KiB
Markdown
# 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/<id>/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/<name>/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/<name>/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 <name> <agent-id>` — añade la entrada `schedules:` a
|
|
`agents/<agent-id>/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/<id>/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.
|