# Plan: Cron scheduler para actividad autónoma de los bots

## Objetivo
Que los bots puedan publicar mensajes, ejecutar tareas o interactuar en salas
de forma autónoma según un horario — sin que el usuario tenga que escribirles.

## Estado: pendiente

---

## Casos de uso
- Bot saluda "buenos días" en una sala a las 9:00
- Devops-bot hace healthcheck de servidores cada hora y reporta
- Assistant-bot publica un resumen diario a las 18:00
- Bots conversan entre sí a horas fijas para simular actividad

---

## Diseño

### Config YAML — `schedules` (ya existe en el schema)
```yaml
schedules:
  - cron: "0 9 * * *"           # cada día a las 9:00
    action: send_message
    room: "!roomid:server.com"
    template: "prompts/good-morning.md"   # se envía como mensaje o como prompt al LLM

  - cron: "0 * * * *"           # cada hora
    action: run_tool
    tool: ssh_command
    args:
      host: "prod-server"
      command: "systemctl is-active myapp"

  - cron: "0 18 * * *"
    action: llm_prompt
    room: "!roomid:server.com"
    prompt: "Genera un resumen del día de hoy para el equipo."
```

### Tipos de acción de cron
| Tipo            | Descripción                                           |
|-----------------|-------------------------------------------------------|
| `send_message`  | Envía un mensaje literal o desde plantilla a una sala |
| `run_tool`      | Ejecuta una herramienta (SSH, HTTP, etc.)             |
| `llm_prompt`    | Llama al LLM con un prompt y publica la respuesta     |

---

## Implementación: `shell/cron/`

```go
// Scheduler lanza goroutines para cada schedule configurado
type Scheduler struct {
    agent   *agents.Agent
    cfg     []config.ScheduleCfg
    effects *effects.Runner
}

func (s *Scheduler) Start(ctx context.Context)
func (s *Scheduler) Stop()
```

Usa `time.AfterFunc` o una librería cron mínima.

### Librería cron recomendada
`github.com/robfig/cron/v3` — ligera, soporta sintaxis cron estándar y `@every 1h`.
Sin dependencias de CGO.

### Integración en `agents/runtime.go`
```go
type Agent struct {
    ...
    scheduler *cron.Scheduler   // nil si no hay schedules
}

func (a *Agent) Start(ctx) error {
    ...
    if len(a.cfg.Schedules) > 0 {
        a.scheduler = cron.New(a, a.cfg.Schedules, a.runner)
        a.scheduler.Start(ctx)
    }
}
```

### Flujo para `llm_prompt`
1. El cron dispara
2. Construir `CompletionRequest` con el prompt del schedule
3. Llamar al LLM (usando `shell/llm/`)
4. Emitir `SendMessageAction` con la respuesta
5. El Runner lo envía a la sala Matrix configurada

---

## Archivos a crear/modificar
- `shell/cron/scheduler.go` — Scheduler, parseador de ScheduleCfg
- `shell/cron/actions.go` — ejecutores de cada tipo de acción de cron
- `internal/config/schema.go` — revisar/completar `ScheduleCfg` (ya tiene campos)
- `agents/runtime.go` — instanciar y arrancar el Scheduler
- `go.mod` — añadir `github.com/robfig/cron/v3`

## Notas
- El Scheduler corre en goroutines separadas; respetar el `ctx` de shutdown
- Los prompts de los schedules pueden ser strings inline o rutas a archivos `.md`
- Fase 1: solo `send_message` y `llm_prompt`
- Fase 2: `run_tool` con resultado incluido en el mensaje
- Fase 3: schedules de interacción entre bots (bot-A pide a bot-B que haga algo)
