From 39e118e2c720021e785a60b81bba969aa810cf43 Mon Sep 17 00:00:00 2001 From: Enmanuel Date: Thu, 9 Apr 2026 00:29:08 +0000 Subject: [PATCH] chore: eliminar issues completados del directorio pendiente MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Los issues 0027, 0028 y 0031 fueron reintroducidos por el merge de quick/claude-skills (basada en master pre-limpieza). Se eliminan definitivamente — las copias en completed/ son la version final. Co-Authored-By: Claude Opus 4.6 (1M context) --- dev/issues/0027-prune-config-schema.md | 112 ---------------- dev/issues/0028-decouple-launcher.md | 109 --------------- dev/issues/0031-expand-file-tools.md | 179 ------------------------- 3 files changed, 400 deletions(-) delete mode 100644 dev/issues/0027-prune-config-schema.md delete mode 100644 dev/issues/0028-decouple-launcher.md delete mode 100644 dev/issues/0031-expand-file-tools.md diff --git a/dev/issues/0027-prune-config-schema.md b/dev/issues/0027-prune-config-schema.md deleted file mode 100644 index 63e7995..0000000 --- a/dev/issues/0027-prune-config-schema.md +++ /dev/null @@ -1,112 +0,0 @@ -# 0027 — Limpiar config schema: eliminar codigo muerto - -## Objetivo - -Eliminar las secciones del config schema (`internal/config/schema.go`) que no estan implementadas ni referenciadas en el codebase. Reducir de 560 lineas / 61 structs a solo lo que realmente se usa. - -## Contexto - -- `internal/config/schema.go` tiene 560 lineas y 61 tipos struct -- Secciones **nunca referenciadas** en ningun archivo `.go`: - - `ObservabilityCfg` (metrics, tracing, health) — 0 usos - - `ResilienceCfg` (circuit breaker, retry, queue) — 0 usos - - `AgentsCfg` (peers, delegation, protocol) — 0 usos - - `PersonalityCfg.Communication` (18 campos: humor, quirks, catchphrases) — 0 usos -- El template `_template/config.yaml` tiene 414 lineas cuando un agente real necesita ~40 -- Esto complica el onboarding y crea confusion sobre que es funcional vs especulativo - -## Arquitectura - -``` -internal/config/schema.go → eliminar structs muertos (~180 lineas) -agents/_template/config.yaml → reducir a lo esencial (~60 lineas) -``` - -### Patron pure core / impure shell - -- `pkg/` — sin cambios -- `shell/` — sin cambios -- `agents/` — template simplificado -- `internal/config/` — poda de tipos - -## Tareas - -### Fase 1: Auditar uso real - -- [ ] **1.1** Grep cada struct/campo del schema contra todo el codebase para confirmar cuales tienen 0 referencias -- [ ] **1.2** Documentar en este issue la lista final de tipos a eliminar - -### Fase 2: Podar schema.go - -- [ ] **2.1** Eliminar `ObservabilityCfg` y todos sus sub-structs (LoggingCfg, MetricsCfg, HealthCfg, TracingCfg) -- [ ] **2.2** Eliminar `ResilienceCfg` y sub-structs (CircuitBreakerCfg, RetryCfg, ShutdownCfg, QueueCfg) -- [ ] **2.3** Eliminar `AgentsCfg` y sub-structs (PeerCfg, DelegationCfg) -- [ ] **2.4** Eliminar campos no usados de `PersonalityCfg` (Communication, Humor, Quirks, etc.) -- [ ] **2.5** Verificar que los campos eliminados no rompen el parsing YAML (yaml.v3 ignora campos extra por defecto) - -### Fase 3: Simplificar template - -- [ ] **3.1** Reescribir `agents/_template/config.yaml` con solo los campos funcionales (~60 lineas) -- [ ] **3.2** Añadir comentarios explicativos en el template para cada seccion - -### Fase 4: Tests - -- [ ] **4.1** Verificar que los configs existentes (`assistant-bot`, `asistente-2`, `meteorologo`) siguen parseando correctamente -- [ ] **4.2** `go build -tags goolm ./...` compila -- [ ] **4.3** `go test -tags goolm ./...` pasa - -### Fase 5: Cleanup - -- [ ] **5.1** Actualizar `CLAUDE.md` si se mencionan secciones eliminadas -- [ ] **5.2** Si algun config YAML existente usa campos eliminados, limpiar esas lineas - ---- - -## Ejemplo de uso - -Antes (template 414 lineas): -```yaml -personality: - tone: friendly - communication: - formality: informal # nunca se usa - humor: light # nunca se usa - quirks: ["dice 'vale'"] # nunca se usa -observability: # nunca se usa - logging: ... - metrics: ... -resilience: # nunca se usa - circuit_breaker: ... -``` - -Despues (template ~60 lineas): -```yaml -agent: - id: mi-agente - description: "Descripcion" -personality: - tone: friendly - language: es -llm: - primary: - provider: openai - model: gpt-4o -matrix: - threads: - enabled: true -``` - -## Decisiones de diseno - -- **Eliminar, no comentar**: codigo muerto se borra, no se comenta con "// TODO: implement" -- **Si se necesita en el futuro, se re-añade**: Git tiene historial. No mantener especulacion. -- **yaml.v3 es tolerante**: campos extra en YAML no causan error, asi que eliminar structs no rompe configs existentes que tengan esos campos - -## Prerequisitos - -- Ninguno - -## Riesgos - -- **Falso negativo en grep**: algun campo podria usarse via reflection o string matching. Mitigacion: buscar tambien por nombre de campo en strings -- **Configs de usuarios existentes**: si alguien tiene un config con `observability:`, no rompera (yaml.v3 ignora), pero el campo sera silenciosamente ignorado. Esto ya era el caso. diff --git a/dev/issues/0028-decouple-launcher.md b/dev/issues/0028-decouple-launcher.md deleted file mode 100644 index ef3af62..0000000 --- a/dev/issues/0028-decouple-launcher.md +++ /dev/null @@ -1,109 +0,0 @@ -# 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//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 diff --git a/dev/issues/0031-expand-file-tools.md b/dev/issues/0031-expand-file-tools.md deleted file mode 100644 index 1d4d7b4..0000000 --- a/dev/issues/0031-expand-file-tools.md +++ /dev/null @@ -1,179 +0,0 @@ -# 0031 — Expandir tools/file/ con write, list, append, delete - -## Objetivo - -Ampliar el paquete `tools/file/` con operaciones de escritura, listado, append y borrado. Mantener el patron deny-by-default, validacion de symlinks, y respetar el flag `read_only` del config. - -## Contexto - -- `tools/file/file.go` actualmente solo tiene `read_file` (107 lineas) -- Seguridad existente: deny-by-default, symlink resolution via `EvalSymlinks`, output truncation a 64KB -- Helpers existentes: `validatePath()` y `resolveReal()` ya estan listos para reutilizarse -- Config `FileOpsCfg` tiene campos `AllowedPaths []string` y `ReadOnly bool` — ReadOnly ya existe pero no se usa porque no hay operaciones de escritura -- Los agentes necesitan interactuar con carpetas de trabajo (workspaces, proyectos, outputs) - -## Arquitectura - -``` -tools/file/file.go → mantener read_file + validatePath (existente) -tools/file/write.go NEW → write_file tool -tools/file/list.go NEW → list_directory tool -tools/file/append.go NEW → append_file tool -tools/file/delete.go NEW → delete_file tool -tools/file/file_test.go → ampliar tests existentes -tools/file/write_test.go NEW → tests de escritura -tools/file/list_test.go NEW → tests de listado -tools/file/delete_test.go NEW → tests de borrado -agents/runtime.go → registrar nuevas tools en buildToolRegistry() -``` - -### Patron pure core / impure shell - -- `pkg/` — sin cambios -- `tools/file/` — cada tool sigue el patron Def (puro) + Exec (impuro) -- `agents/` — solo cambio en registro de tools - -## Tareas - -### Fase 1: Refactor de validacion compartida - -- [ ] **1.1** Extraer `validatePath()` y `resolveReal()` a `tools/file/validate.go` (ya son funciones internas, solo moverlas para reutilizarlas) -- [ ] **1.2** Crear helper `validateWritePath(absPath, cfg)` que ademas verifica `ReadOnly == false` - -### Fase 2: write_file - -- [ ] **2.1** Crear `tools/file/write.go` con `NewWriteFile(cfg) tools.Tool` -- [ ] **2.2** Parametros: `path` (string, required), `content` (string, required) -- [ ] **2.3** Validaciones: - - Rechazar si `cfg.ReadOnly == true` - - `validatePath()` contra AllowedPaths - - Crear directorios padre si no existen (`os.MkdirAll`) - - Limite de contenido: max 1MB de input -- [ ] **2.4** Devolver confirmacion con bytes escritos y path - -### Fase 3: list_directory - -- [ ] **3.1** Crear `tools/file/list.go` con `NewListDirectory(cfg) tools.Tool` -- [ ] **3.2** Parametros: `path` (string, required), `recursive` (boolean, optional, default false) -- [ ] **3.3** Validaciones: - - `validatePath()` contra AllowedPaths - - Limite de entries: max 500 archivos en el output - - No seguir symlinks fuera de AllowedPaths -- [ ] **3.4** Output: lista con nombre, tamaño, tipo (file/dir), fecha modificacion - -### Fase 4: append_file - -- [ ] **4.1** Crear `tools/file/append.go` con `NewAppendFile(cfg) tools.Tool` -- [ ] **4.2** Parametros: `path` (string, required), `content` (string, required) -- [ ] **4.3** Validaciones: - - Rechazar si `cfg.ReadOnly == true` - - `validatePath()` contra AllowedPaths - - Si el archivo no existe, crearlo (igual que write) - - Limite de tamaño: verificar que archivo existente + contenido nuevo < 10MB -- [ ] **4.4** Devolver confirmacion con bytes añadidos y tamaño total - -### Fase 5: delete_file - -- [ ] **5.1** Crear `tools/file/delete.go` con `NewDeleteFile(cfg) tools.Tool` -- [ ] **5.2** Parametros: `path` (string, required) -- [ ] **5.3** Validaciones: - - Rechazar si `cfg.ReadOnly == true` - - `validatePath()` contra AllowedPaths - - **Solo archivos**: no permitir borrar directorios (prevencion de `rm -rf` accidental) - - Resolver symlinks antes de borrar (no borrar el symlink si apunta fuera de AllowedPaths) -- [ ] **5.4** Devolver confirmacion con path eliminado - -### Fase 6: Registro en runtime - -- [ ] **6.1** En `agents/runtime.go` → `buildToolRegistry()`, registrar las 4 tools nuevas condicionalmente: - ```go - if cfg.Tools.FileOps.Enabled { - reg.Register(file.NewReadFile(cfg.Tools.FileOps)) - if !cfg.Tools.FileOps.ReadOnly { - reg.Register(file.NewWriteFile(cfg.Tools.FileOps)) - reg.Register(file.NewAppendFile(cfg.Tools.FileOps)) - reg.Register(file.NewDeleteFile(cfg.Tools.FileOps)) - } - reg.Register(file.NewListDirectory(cfg.Tools.FileOps)) - } - ``` -- [ ] **6.2** `list_directory` se registra siempre (no requiere escritura) - -### Fase 7: Tests - -- [ ] **7.1** Test: `write_file` crea archivo nuevo en AllowedPaths -- [ ] **7.2** Test: `write_file` rechaza si ReadOnly es true -- [ ] **7.3** Test: `write_file` rechaza paths fuera de AllowedPaths -- [ ] **7.4** Test: `write_file` rechaza contenido > 1MB -- [ ] **7.5** Test: `list_directory` lista correctamente archivos y subdirectorios -- [ ] **7.6** Test: `list_directory` respeta limite de 500 entries -- [ ] **7.7** Test: `list_directory` no sigue symlinks fuera de AllowedPaths -- [ ] **7.8** Test: `append_file` añade contenido al final -- [ ] **7.9** Test: `append_file` crea archivo si no existe -- [ ] **7.10** Test: `delete_file` borra archivo existente -- [ ] **7.11** Test: `delete_file` rechaza borrar directorios -- [ ] **7.12** Test: `delete_file` rechaza si ReadOnly es true -- [ ] **7.13** Test: symlink que apunta fuera de AllowedPaths es rechazado en todas las tools -- [ ] **7.14** Test: path traversal (`../`) es rechazado en todas las tools - -### Fase 8: Cleanup - -- [ ] **8.1** Actualizar `CLAUDE.md` seccion de tools con las nuevas herramientas -- [ ] **8.2** Actualizar `.claude/rules/create_tool.md` si hay nuevos patrones -- [ ] **8.3** `go build -tags goolm ./...` y `go test -tags goolm ./...` - ---- - -## Ejemplo de uso - -Config del agente: -```yaml -tools: - file: - enabled: true - allowed_paths: - - "/home/ubuntu/workspace/proyecto-x" - read_only: false -``` - -Interaccion en Element: -``` -Usuario: Lista los archivos en /home/ubuntu/workspace/proyecto-x/src -Bot: [usa list_directory] Encontre 12 archivos: - - main.go (2.3 KB, 2026-04-01) - - handler.go (1.1 KB, 2026-04-02) - - ... - -Usuario: Escribe un archivo test.txt con "hola mundo" -Bot: [usa write_file] Archivo creado: /home/ubuntu/workspace/proyecto-x/test.txt (10 bytes) - -Usuario: Añade una linea mas al test.txt -Bot: [usa append_file] Contenido añadido: 15 bytes (total: 25 bytes) - -Usuario: Borra el test.txt -Bot: [usa delete_file] Archivo eliminado: /home/ubuntu/workspace/proyecto-x/test.txt -``` - -Intento fuera de AllowedPaths: -``` -Usuario: Lee /etc/passwd -Bot: Error: path "/etc/passwd" not under any allowed path -``` - -## Decisiones de diseno - -- **ReadOnly como gate**: `write_file`, `append_file`, `delete_file` solo se registran si `ReadOnly == false`. `read_file` y `list_directory` siempre se registran si file tools esta habilitado -- **Solo archivos en delete**: borrar directorios es demasiado peligroso para un agente autonomo. Si necesita borrar un directorio, puede borrar archivos uno por uno -- **Limites de tamaño**: 1MB para write (evita saturar disco), 64KB para read output (evita saturar contexto LLM), 500 entries para list (evita listados enormes) -- **Crear padres automaticamente**: `write_file` hace `MkdirAll` para crear la estructura de directorios. Simplifica el uso sin riesgo de seguridad (los paths padre tambien estan bajo AllowedPaths) -- **Reutilizar validatePath()**: misma logica de seguridad para todas las operaciones. Un solo punto de validacion - -## Prerequisitos - -- Ninguno - -## Riesgos - -- **Escritura accidental**: un agente con LLM podria decidir escribir archivos incorrectos. Mitigacion: AllowedPaths restringe donde puede escribir, y el system prompt debe instruir al agente sobre cuando escribir -- **Race conditions**: dos agentes escribiendo el mismo archivo. Mitigacion: file locking no es necesario en la primera version; los agentes tipicamente tienen workspaces separados -- **Disk exhaustion**: un agente escribiendo en loop. Mitigacion: rate limiting del tool registry + limite de 1MB por write