8f6958f856
Registra los nuevos issues pendientes en el indice y excluye la carpeta worktrees/ del control de versiones. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
110 lines
4.1 KiB
Markdown
110 lines
4.1 KiB
Markdown
# 0028 — Desacoplar launcher del registro estatico de agentes
|
|
|
|
## Objetivo
|
|
|
|
Eliminar la necesidad de editar `cmd/launcher/main.go` cada vez que se añade un agente. Reemplazar el `rulesRegistry` hard-coded con auto-discovery basado en la convencion de directorios.
|
|
|
|
## Contexto
|
|
|
|
- Actualmente `cmd/launcher/main.go` importa cada paquete de agente explicitamente:
|
|
```go
|
|
import (
|
|
assistantagent "github.com/enmanuel/agents/agents/assistant-bot"
|
|
asistente2agent "github.com/enmanuel/agents/agents/asistente-2"
|
|
)
|
|
var rulesRegistry = map[string]func() []decision.Rule{...}
|
|
```
|
|
- Cada agente nuevo requiere: añadir import + añadir entrada al map + recompilar
|
|
- El script `dev-scripts/agent/new-agent.sh` ya modifica el launcher automaticamente, pero es fragil (sed sobre codigo Go)
|
|
- Contradiccion: el launcher hace glob de `agents/*/config.yaml` para descubrir configs, pero luego necesita imports estaticos para las reglas
|
|
|
|
## Arquitectura
|
|
|
|
```
|
|
agents/registry.go NEW → registro global de reglas (init-based)
|
|
agents/<id>/agent.go → cada agente se auto-registra via init()
|
|
cmd/launcher/main.go → eliminar rulesRegistry, usar agents.GetRules(id)
|
|
```
|
|
|
|
### Patron pure core / impure shell
|
|
|
|
- `pkg/` — sin cambios
|
|
- `shell/` — sin cambios
|
|
- `agents/` — nuevo registry global + init() en cada agente
|
|
- `cmd/launcher/` — simplificacion
|
|
|
|
## Tareas
|
|
|
|
### Fase 1: Crear registry de reglas
|
|
|
|
- [ ] **1.1** Crear `agents/registry.go` con `Register(id, rulesFn)` y `GetRules(id)`
|
|
- [ ] **1.2** Usar sync.Mutex o sync.Map para seguridad en init()
|
|
|
|
### Fase 2: Migrar agentes a auto-registro
|
|
|
|
- [ ] **2.1** En `agents/assistant-bot/agent.go` añadir `func init() { agents.Register("assistant-bot", Rules) }`
|
|
- [ ] **2.2** Repetir para `asistente-2` y `meteorologo`
|
|
- [ ] **2.3** Actualizar `agents/_template/agent.go` con el patron init()
|
|
|
|
### Fase 3: Simplificar launcher
|
|
|
|
- [ ] **3.1** Eliminar imports explicitos de agentes en `cmd/launcher/main.go`
|
|
- [ ] **3.2** Añadir blank import: `_ "github.com/enmanuel/agents/agents/assistant-bot"` (etc.)
|
|
- [ ] **3.3** Reemplazar `rulesRegistry[id]` con `agents.GetRules(id)`
|
|
- [ ] **3.4** Si no hay reglas registradas para un agent id, log warning y usar reglas vacias (command-only bot)
|
|
|
|
### Fase 4: Actualizar scripts
|
|
|
|
- [ ] **4.1** Simplificar `dev-scripts/agent/new-agent.sh` — ya no necesita editar el map, solo añadir blank import
|
|
- [ ] **4.2** Actualizar `.claude/rules/create_agent.md` con el nuevo patron
|
|
|
|
### Fase 5: Tests
|
|
|
|
- [ ] **5.1** Test para `agents/registry.go` (register, get, get-missing)
|
|
- [ ] **5.2** `go build -tags goolm ./...` compila
|
|
- [ ] **5.3** `go test -tags goolm ./...` pasa
|
|
|
|
### Fase 6: Cleanup
|
|
|
|
- [ ] **6.1** Actualizar `CLAUDE.md` seccion sobre registro en launcher
|
|
- [ ] **6.2** Eliminar codigo muerto del launcher
|
|
|
|
---
|
|
|
|
## Ejemplo de uso
|
|
|
|
Antes (crear agente):
|
|
```go
|
|
// cmd/launcher/main.go — editar manualmente
|
|
import newagent "github.com/enmanuel/agents/agents/new-bot"
|
|
var rulesRegistry = map[string]func() []decision.Rule{
|
|
"new-bot": newagent.Rules, // añadir esta linea
|
|
}
|
|
```
|
|
|
|
Despues:
|
|
```go
|
|
// agents/new-bot/agent.go — auto-registro
|
|
func init() {
|
|
agents.Register("new-bot", Rules)
|
|
}
|
|
|
|
// cmd/launcher/main.go — solo blank import
|
|
import _ "github.com/enmanuel/agents/agents/new-bot"
|
|
```
|
|
|
|
## Decisiones de diseno
|
|
|
|
- **init() + blank import**: patron estandar en Go (database/sql drivers, image codecs). Simple y familiar
|
|
- **Blank imports en launcher**: siguen siendo estaticos en el codigo, pero son una linea trivial sin logica. El script de scaffolding puede añadirla sin riesgo de romper sintaxis Go
|
|
- **No plugin system dinamico**: Go no tiene plugins portables. init() es el mecanismo idomatic
|
|
|
|
## Prerequisitos
|
|
|
|
- Ninguno (puede hacerse independiente de otros issues)
|
|
|
|
## Riesgos
|
|
|
|
- **Orden de init()**: Go garantiza init() dentro de un paquete, pero no entre paquetes. Mitigacion: el registro es un map simple, el orden no importa
|
|
- **Olvidar blank import**: si no se añade el blank import, el agente no se registra y el launcher lo trata como command-only. Mitigacion: el script de scaffolding lo añade automaticamente
|