diff --git a/.claude/commands/create-issue.md b/.claude/commands/create-issue.md new file mode 100644 index 0000000..5b390d5 --- /dev/null +++ b/.claude/commands/create-issue.md @@ -0,0 +1,154 @@ +# Command: create issue + +Crea un issue nuevo en `dev/issues/` siguiendo **estrictamente** la regla `create_issue.md`. Si el issue es grande, lo desglosa automaticamente en sub-issues con feature flags. + +## Inputs + +Se necesitan los datos del issue. Si no se proporcionan, preguntar. + +- `titulo`: titulo corto y descriptivo (ej: "Hot reload de configuracion") +- `descripcion`: objetivo/descripcion de lo que se quiere lograr +- `dependencias` (opcional): issues de los que depende (ej: "Requiere issue 0010") + +## Flujo obligatorio + +### 1. Determinar el numero del issue + +Buscar el numero mas alto en `dev/issues/` y `dev/issues/completed/` y usar el siguiente. +Formato: 4 digitos con ceros a la izquierda (`0023`, `0024`, etc.). + +```bash +ls dev/issues/ dev/issues/completed/ | grep -oP '^\d{4}' | sort -rn | head -1 +``` + +### 2. Generar slug + +A partir del titulo: +- Lowercase +- Palabras separadas por guiones +- Conciso (2-4 palabras) +- Ejemplo: "Hot reload de configuracion" → `hot-reload` + +### 3. Evaluar tamano del issue + +Antes de escribir el issue, analizar el alcance y determinar si cabe en **una sola rama corta (horas)**. + +**Criterios para desglosar en sub-issues:** +- Toca mas de 2 capas del patron (pkg/ + shell/ + agents/ + tools/) +- Requiere mas de ~3 fases de implementacion +- El usuario lo indica explicitamente +- La descripcion implica multiples componentes independientes + +**Si es un issue simple** (cabe en una rama): +- Crear un solo archivo `dev/issues/-.md` +- Seguir directo al paso 4 + +**Si es un issue grande** (necesita desglose): +- Crear el issue principal `dev/issues/-.md` con seccion `## Desglose multi-issue` +- Crear cada sub-issue como `dev/issues/-.md` (ej: `0023a-types`, `0023b-client`) +- Cada sub-issue es autocontenido: debe compilar, pasar tests, no romper master +- Agregar feature flag en la descripcion del issue principal +- Registrar todos los sub-issues en `dev/issues/README.md` + +### 4. Crear el issue desde el template + +Copiar `.claude/templates/issue.md` y rellenar **todas** las secciones: + +- **Objetivo**: 1-3 frases claras +- **Contexto**: que existe, que falta, dependencias +- **Arquitectura**: archivos afectados (marcar `NEW` los nuevos). Explicar que va en `pkg/` (puro) vs `shell/` (impuro) +- **Tareas**: fases con tareas numeradas (`1.1`, `1.2`, etc.). Cada tarea concreta y verificable. Siempre incluir fase de tests y fase de cleanup/docs +- **Ejemplo de uso**: flujo concreto +- **Decisiones de diseno**: justificaciones clave +- **Prerequisitos**: que debe existir antes +- **Riesgos**: problemas potenciales y mitigacion + +### 5. Para issues multi-issue — contenido adicional + +En el issue principal, agregar despues de las tareas: + +```markdown +## Desglose multi-issue + +Este issue se implementa en sub-issues independientes, cada uno en su propia rama. + +| Sub-issue | Rama | Alcance | Estado | +|-----------|------|---------|--------| +| a- | issue/a- | | pendiente | +| b- | issue/b- | | pendiente | +| ... + +### Feature flag + +Nombre: `` +Se activa en el ultimo sub-issue cuando todo esta integrado. + +### Progreso por tarea + +- [ ] **1.1** — sub-issue a +- [ ] **1.2** — sub-issue a +- [ ] **2.1** — sub-issue b +... +``` + +Cada sub-issue individual debe tener su propio archivo con: +- Objetivo especifico del sub-issue +- Tareas que le corresponden del issue principal +- Nota de que es parte de un issue mayor + +### 6. Registrar feature flag (solo multi-issue) + +Actualizar `dev/feature_flags.json`: + +```json +{ + "": { + "enabled": false, + "issue": "", + "description": "", + "added": "" + } +} +``` + +### 7. Actualizar el indice + +En `dev/issues/README.md`, agregar filas al final de la tabla. + +**Issue simple:** +```markdown +| | | [-.md](-.md) | pendiente | +``` + +**Issue multi-issue (agregar fila por cada sub-issue tambien):** +```markdown +| | | [-.md](-.md) | pendiente | +| a | (parte a) | [a-.md](a-.md) | pendiente | +| b | (parte b) | [b-.md](b-.md) | pendiente | +``` + +### 8. Verificar + +- [ ] Archivo(s) creado(s) en `dev/issues/` +- [ ] Todas las secciones del template rellenadas +- [ ] Fila(s) agregada(s) en `dev/issues/README.md` +- [ ] Numero de issue es consecutivo (sin saltos ni duplicados) +- [ ] Si es multi-issue: sub-issues creados, feature flag en `dev/feature_flags.json`, seccion de desglose en issue principal + +### 9. Reportar al usuario + +Mostrar resumen: +- Numero y titulo del issue +- Si fue desglosado: listar sub-issues con su alcance +- Recordar: usar `/fix-issue ` (o `/fix-issue a`, `b`, etc.) para implementar + +## Reglas criticas + +- Seguir `create_issue.md` de forma estricta +- **Patron pure core / impure shell**: toda feature debe explicar que va en `pkg/` vs `shell/` +- **Tareas atomicas**: cada tarea debe ser implementable de forma independiente +- **Numeracion continua**: nunca reusar numeros +- **Estado**: issues nuevos siempre `pendiente` +- **Issues grandes**: desglosar en sub-issues con feature flags, nunca dejar una rama abierta por dias +- **Feature flag != WIP**: un flag protege codigo terminado y testeado, no codigo a medias +- **No commitear**: este comando solo crea archivos en `dev/issues/`. No hace commits ni crea ramas diff --git a/.claude/commands/fix-issue.md b/.claude/commands/fix-issue.md new file mode 100644 index 0000000..2022d32 --- /dev/null +++ b/.claude/commands/fix-issue.md @@ -0,0 +1,96 @@ +# Command: fix issue + +Ejecuta de punta a punta el flujo de implementacion/cierre de un issue siguiendo **estrictamente** la regla `fix_issue.md`. + +## Inputs + +Se necesita el issue objetivo. Si no se proporciona, preguntar. + +- `issue`: numero o nombre (ej: `0010` o `0010-access-control`) + +## Flujo obligatorio + +1. Resolver el issue objetivo: + +- Si viene solo numero (`0010`), buscar `dev/issues/0010-*.md`. +- Si viene slug completo (`0010-access-control`), usar `dev/issues/0010-access-control.md`. +- Si no existe en `dev/issues/`, **STOP** e informar al usuario. +- Si ya esta en `dev/issues/completed/`, **STOP** e informar al usuario. + +2. Leer completo el issue y extraer: + +- objetivo +- tareas/fases +- arquitectura y limites (pure core / impure shell) + +3. Crear rama de trabajo (inline, sin invocar `/git-branch`): + +Verificar la rama actual: + +```bash +git branch --show-current +``` + +- Si ya estamos en `issue/-` que coincide con el issue → continuar directamente a paso 4. +- Si estamos en `master` o cualquier otra rama → crear la rama: + +```bash +git checkout master +git pull --rebase +git checkout -b issue/- +``` + +Nunca trabajar directamente en `master`. + +4. Planificar con `TodoWrite`: + +- Crear plan basado en las tareas del issue. +- Respetar el orden de fases. +- Incluir siempre una tarea de tests. + +5. Implementar el issue completo: + +- Ejecutar tareas en orden. +- Respetar pure core / impure shell (`pkg/` puro, `shell/` impuro). +- Compilar frecuentemente: `go build -tags goolm ./...`. +- Marcar progreso en `TodoWrite` al completar cada bloque. + +6. Tests obligatorios: + +```bash +go test -tags goolm ./... +``` + +- Si falla, corregir antes de continuar. +- No cerrar el issue sin tests pasando. + +7. Feature flags (si aplica): + +- Evaluar si es feature multi-issue o despliegue gradual. +- Si aplica, actualizar `dev/feature_flags.json` en el commit correspondiente. +- No usar flags para esconder codigo incompleto. + +8. Cerrar el issue al terminar: + +```bash +mv dev/issues/-.md dev/issues/completed/ +``` + +Actualizar `dev/issues/README.md`: + +- Link a `completed/-.md` +- Estado a `completado` + +9. Integrar/publicar con `/git-push`: + +```text +/git-push +``` + +## Reglas criticas + +- Seguir `fix_issue.md` de forma estricta. +- No saltear tareas del issue. +- No hacer commits WIP. +- Commits atomicos por bloque logico (`feat:`, `fix:`, `test:`, `docs:`, `refactor:`, `chore:`). +- Siempre usar `-tags goolm` en build/test. \ No newline at end of file diff --git a/.claude/commands/git-branch.md b/.claude/commands/git-branch.md new file mode 100644 index 0000000..b2c6074 --- /dev/null +++ b/.claude/commands/git-branch.md @@ -0,0 +1,86 @@ +# Command: git branch (TBD) + +Crea una rama de trabajo. **Nunca trabajar directamente en master.** + +Soporta dos tipos de rama: +- `issue/-` — para implementar un issue existente de `dev/issues/` +- `quick/` — para cambios pequeños sin issue asociado (fixes, config, docs, etc.) + +## Inputs + +Preguntar al usuario si el cambio esta asociado a un issue o no. + +### Si es un issue: +- `issue_number`: numero de 4 digitos (e.g. `0020`) +- `slug`: nombre corto separado por guiones (e.g. `hot-reload`) + +### Si es un cambio rapido (sin issue): +- `slug`: nombre corto descriptivo separado por guiones (e.g. `fix-typo-readme`) + +## Flujo obligatorio + +1. Verificar que estamos en master y limpio: + +```bash +git branch --show-current +git status --short +``` + +Si no estamos en master, cambiar primero: + +```bash +git checkout master +``` + +Si hay cambios sin commitear, **avisar al usuario** y no continuar hasta resolver. + +2. Actualizar master desde remoto: + +```bash +git pull --rebase +``` + +3. Crear la rama y cambiar a ella: + +**Para issues:** +```bash +git checkout -b issue/- +``` +Ejemplo: `git checkout -b issue/0013-hot-reload` + +**Para cambios rapidos:** +```bash +git checkout -b quick/ +``` +Ejemplo: `git checkout -b quick/fix-typo-readme` + +4. Confirmar al usuario: + +``` +Rama `` creada desde master actualizado. +Puedes empezar a trabajar. Cuando termines, usa `/git-push` para integrar a master. +``` + +## Convenciones + +- **Formato de rama issue**: `issue/-` (siempre 4 digitos) +- **Formato de rama quick**: `quick/` (sin numero) +- **Ramas cortas**: idealmente horas, no dias +- **Una rama por issue**: no mezclar issues en la misma rama +- **Nunca pushear la rama al remoto**: el push se hace desde master despues del merge +- **No rebase interactivo**: si los commits son limpios desde el inicio, no reescribir historia +- **No commits WIP**: cada commit en la rama debe ser atomico y con mensaje real (ver convencion en `/git-push`) + +## Features multi-issue + +Para features que no caben en una sola rama, usar sub-issues con sufijo letra: + +``` +issue/0015a-telegram-types +issue/0015b-telegram-client +issue/0015c-telegram-listener +issue/0015d-telegram-enable +``` + +Cada sub-rama sigue el mismo flujo: crear → implementar → merge --no-ff → delete. +El codigo parcial se protege con **feature flags** en `dev/feature_flags.json` (no con commits WIP). diff --git a/.claude/commands/git-push.md b/.claude/commands/git-push.md new file mode 100644 index 0000000..89ba52c --- /dev/null +++ b/.claude/commands/git-push.md @@ -0,0 +1,157 @@ +# Command: git push + +Integra cambios a master y publica. Soporta ramas `issue/*` y `quick/*`. + +## Flujo obligatorio + +### 1. Verificar rama actual y estado + +```bash +git branch --show-current +git status --short +``` + +#### Si estamos en una rama `issue/*` o `quick/*` + +Continuar directamente al paso 2. + +#### Si estamos en `master` con cambios pendientes + +Crear una rama automaticamente antes de continuar: + +1. Preguntar al usuario: **¿Este cambio esta asociado a un issue existente?** +2. **Si es un issue**: pedir el numero y slug, crear rama `issue/-`. +3. **Si NO es un issue**: pedir un slug descriptivo, crear rama `quick/`. + +```bash +# Para issues: +git checkout -b issue/- +# Para cambios rapidos: +git checkout -b quick/ +``` + +4. Continuar al paso 2 con los cambios ya en la rama nueva. + +**IMPORTANTE**: No inventar numeros de issue. Solo usar `issue/` si el issue existe en `dev/issues/`. + +#### Si estamos en `master` sin cambios + +**STOP**: no hay nada que publicar. + +### 2. Revisar cambios y crear commits por bloque + +```bash +git status --short +git diff --stat +git diff +``` + +Crear commits **atomicos por bloque logico**. Cada commit agrupa cambios de la misma naturaleza: + +```bash +git add +git commit -m ": " -m "Descripcion larga en espanol explicando que cambia, por que se hizo, impacto esperado y alcance del bloque." + +git add +git commit -m ": " -m "Descripcion larga en espanol." +``` + +**Reglas criticas de commits:** +- **No WIP**: nunca commitear "wip", "tmp", "fix fix" ni codigo a medias. Cada commit debe ser atomico y completo. +- **No mezclar tipos**: no combinar `feat:` + `test:` en un mismo commit. Separar por bloque logico. +- **No squash**: los commits individuales se preservan en master via `--no-ff`. Usar `git log --first-parent master` para ver solo merge commits. +- **No rebase interactivo**: si los commits ya son limpios, no reescribir historia. + +### 3. Ejecutar tests + +**Obligatorio antes de mergear.** Si el proyecto tiene tests, ejecutarlos: + +```bash +go test -tags goolm ./... +``` + +- Si los tests **fallan** → **STOP**: corregir antes de continuar. No mergear codigo roto. +- Si los tests **pasan** → continuar al paso 4. +- Si no hay tests aplicables (e.g. solo cambios de docs/config) → indicar al usuario y continuar. + +### 4. Evaluar feature flags + +Feature flags se usan cuando el issue es **parte de una feature multi-issue** o el cambio tiene riesgo y necesita poder desactivarse. **Feature flag ≠ WIP** — un flag protege codigo terminado y testeado, no codigo a medias. + +Si se modifico `dev/feature_flags.json` o si los cambios son parte de una feature que se despliega en fases: + +1. Verificar que `dev/feature_flags.json` existe y esta actualizado. +2. Confirmar que el flag correspondiente tiene el estado correcto (`enabled: true/false`). +3. Incluir el archivo en el commit correspondiente (no crear commit separado solo para flags). + +Si el issue es autocontenido (se completa en esta rama), no necesita flag. Saltar este paso. + +### 5. Actualizar master y hacer merge --no-ff + +```bash +git checkout master +git pull --rebase +git merge --no-ff -m "merge: " +``` + +El merge commit debe tener formato: +- Titulo: `merge: ` +- Cuerpo (opcional): resumen de lo que entra + +Ejemplos: +- `merge: issue/0021-threads-default-config — habilitar threads en agentes` +- `merge: quick/fix-typo-readme — corregir typo en README` + +Si hay conflictos durante el merge: +1. Resolver los conflictos +2. `git add` los archivos resueltos +3. `git commit` (sin -m, para mantener el mensaje de merge) + +### 6. Push a remoto + +```bash +git push +``` + +### 7. Limpiar rama local + +```bash +git branch -d +``` + +### 8. Confirmar al usuario + +``` +Rama `` integrada a master y publicada. +Rama local eliminada. +``` + +## Convencion de commits + +- `feat:` nueva funcionalidad +- `fix:` correccion de error +- `refactor:` cambio estructural sin cambio funcional +- `docs:` documentacion +- `chore:` mantenimiento +- `test:` tests nuevos o modificados +- `merge:` commit de merge (generado por --no-ff) + +## Regla de mensajes + +- El titulo (`-m` corto) debe resumir el bloque. +- El cuerpo (`-m` largo) debe estar en espanol y explicar: + - que se cambio, + - por que se cambio, + - que impacto tiene, + - que no se toco. + +## Checklist rapido + +- [ ] Todos los cambios estan commiteados en una rama `issue/*` o `quick/*`. +- [ ] Se separaron cambios distintos en commits diferentes. +- [ ] Cada commit tiene descripcion larga en espanol. +- [ ] Tests ejecutados y pasando (o no aplican). +- [ ] Feature flags evaluados (o no aplican). +- [ ] `git merge --no-ff` ejecutado desde master. +- [ ] `git push` ejecutado correctamente. +- [ ] Rama local eliminada. diff --git a/dev/issues/0035-audit-trail-metrics.md b/dev/issues/0035-audit-trail-metrics.md new file mode 100644 index 0000000..e92e224 --- /dev/null +++ b/dev/issues/0035-audit-trail-metrics.md @@ -0,0 +1,177 @@ +# 0035 — Observabilidad activa: audit trail + comando !metrics + +**Estado:** pendiente + +## Objetivo + +Activar la infraestructura de auditoría (`AuditCfg`) que ya está definida en `internal/config/schema.go` pero nunca implementada, y añadir un comando `!metrics` que agregue datos del log del día actual. Ambas features usan infraestructura existente (JSONL logs, config schema, command system) sin dependencias nuevas. + +## Contexto + +- `AuditCfg` lleva definida desde el schema original pero el código nunca la consume: no hay writer, no hay emisión de eventos, no hay integración con el runtime. +- Los logs JSONL ya contienen métricas útiles (`duration_ms`, `tokens_used`, `tool_exec_*`, `command_received`) pero no hay forma de consultarlas sin parsear archivos manualmente. +- `shell/logger/query.go` ya tiene helpers para leer y filtrar logs por fecha/campo. +- El command system (`!status`, `!info`) ya existe y es extensible via built-in. + +## Arquitectura + +### Fase 1: Audit trail + +``` +shell/audit/ NEW — audit event writer (archivo JSONL + opcionalmente room Matrix) +shell/audit/writer.go NEW — AuditWriter: escribe eventos a archivo y/o room +``` + +Integración en el runtime existente: +``` +agents/handler.go MOD — emitir eventos audit en puntos clave +agents/runtime.go MOD — inicializar AuditWriter si cfg.Security.Audit.Enabled +tools/registry.go MOD — emitir evento audit en tool_exec +``` + +**Pure core / impure shell:** +- No se añade nada a `pkg/` — los eventos audit son side effects puros (escritura a archivo/Matrix) +- `shell/audit/` es 100% impuro: escribe a disco y opcionalmente envía mensajes Matrix + +### Fase 2: Comando !metrics + +``` +agents/commands.go MOD — añadir cmdMetrics como built-in +pkg/command/builtins.go MOD — añadir spec de !metrics +``` + +El comando lee los JSONL del día actual usando `shell/logger/query.go` (ya existente) y calcula agregados en memoria. No persiste nada, no crea tablas, no necesita SQLite. + +## Tareas + +### Fase 1 — Audit trail + +- [ ] **1.1** Crear `shell/audit/writer.go` con `AuditWriter` struct: + - Constructor `New(cfg AuditCfg, matrixSender func(roomID, msg string), logger *slog.Logger) *AuditWriter` + - Método `Emit(event AuditEvent)` que escribe a `LogFile` (JSONL append) y opcionalmente envía a `LogToRoom` (room Matrix) + - `AuditEvent` struct: `{ Time, AgentID, EventType, SenderID, RoomID, Detail string }` + - Filtrado por `Include` (lista de event types a auditar; vacío = todos) + - Event types iniciales: `command_exec`, `tool_exec`, `llm_request`, `llm_error`, `message_received` + +- [ ] **1.2** Crear `shell/audit/writer_test.go`: + - Test de escritura a archivo (verificar formato JSONL) + - Test de filtrado por `Include` (solo emite los tipos configurados) + - Test con `LogFile` vacío (no escribe a archivo, solo room) + - Test con `LogToRoom` vacío (solo escribe a archivo) + +- [ ] **1.3** Integrar `AuditWriter` en `agents/runtime.go`: + - En `New()`: si `cfg.Security.Audit.Enabled`, crear `AuditWriter` y guardarlo en el struct `Agent` + - Pasar `matrixSender` como closure que usa el cliente Matrix del agente + - Si audit no está habilitado, `AuditWriter` es nil (los call sites hacen nil-check) + +- [ ] **1.4** Emitir eventos en los puntos clave: + - `agents/handler.go` → `message_received` (sender, room, is_dm) + - `agents/handler.go` → `command_exec` (command name, sender) + - `tools/registry.go` → `tool_exec` (tool name, duration, success/error) + - `shell/llm/` → `llm_request` (provider, model, tokens) y `llm_error` (provider, error) + +### Fase 2 — Comando !metrics + +- [ ] **2.1** Añadir spec en `pkg/command/builtins.go`: + ```go + {Name: "metrics", Description: "Métricas agregadas del día actual", Usage: "!metrics"} + ``` + +- [ ] **2.2** Implementar `cmdMetrics` en `agents/commands.go`: + - Leer logs del día actual con `logger.ReadDayLogs(logDir, agentID, time.Now())` + - Calcular: total mensajes recibidos, comandos ejecutados, llamadas LLM (count + tokens totales + latencia media), llamadas a tools (count + errores), errores totales + - Formatear como markdown table para Matrix + - Ejemplo de output: + ``` + **Métricas de hoy (2026-04-09):** + + | Métrica | Valor | + |---------|-------| + | Mensajes recibidos | 42 | + | Comandos ejecutados | 15 | + | Llamadas LLM | 27 | + | Tokens totales | 45,230 | + | Latencia LLM media | 1,250 ms | + | Tool calls | 8 | + | Tool errors | 1 | + | Errores totales | 2 | + | Uptime | 6h 30m | + ``` + +- [ ] **2.3** El handler necesita acceso al `logDir` del agente — pasar via config o campo en Agent struct (ya existe `a.cfg` con el agent ID, solo falta saber el baseDir de logs) + +### Fase 3 — Tests y cleanup + +- [ ] **3.1** Tests para `cmdMetrics`: crear logs JSONL de ejemplo en tmpdir, verificar que los agregados son correctos +- [ ] **3.2** Test de integración: `AuditWriter` + handler emite eventos reales a archivo temporal +- [ ] **3.3** Documentar en `docs/security.md` la sección de audit trail (config YAML de ejemplo) + +## Ejemplo de uso + +### Audit trail + +Config en `agents/asistente-2/config.yaml`: +```yaml +security: + audit: + enabled: true + log_file: "logs/asistente-2/audit.jsonl" + log_to_room: "!audit-room:matrix-af2f3d.organic-machine.com" + include: + - command_exec + - tool_exec + - llm_error +``` + +Resultado en `audit.jsonl`: +```json +{"time":"2026-04-09T10:30:00Z","agent_id":"asistente-2","event":"command_exec","sender":"@user:matrix","room":"!abc:matrix","detail":"!status"} +{"time":"2026-04-09T10:30:05Z","agent_id":"asistente-2","event":"tool_exec","sender":"@user:matrix","room":"!abc:matrix","detail":"http_get duration=350ms ok"} +``` + +### Comando !metrics + +``` +Usuario: !metrics +Bot: +**Métricas de hoy (2026-04-09):** + +| Métrica | Valor | +|---------|-------| +| Mensajes recibidos | 42 | +| Comandos ejecutados | 15 | +| Llamadas LLM | 27 | +| Tokens totales | 45,230 | +| Latencia LLM media | 1,250 ms | +| Tool calls | 8 | +| Tool errors | 1 | +| Errores totales | 2 | +| Uptime | 6h 30m | +``` + +## Decisiones de diseño + +1. **Audit separado de logs normales**: los logs de runtime son para debugging (alto volumen, retención corta). El audit trail es para compliance/revisión (eventos selectivos, retención configurable independiente). + +2. **Sin SQLite para métricas**: el comando `!metrics` calcula en memoria leyendo JSONL del día. Con los volúmenes actuales (~cientos de eventos/día por agente), esto es instantáneo. Si escala, se puede cachear o migrar a SQLite en un issue futuro. + +3. **AuditWriter acepta matrixSender como función**: evita acoplar `shell/audit/` con el cliente Matrix directamente. Sigue el patrón de inyección de dependencias del proyecto. + +4. **Include como allowlist**: lista vacía = auditar todo. Esto es deny-by-default invertido (opt-in por tipo de evento) para evitar audit logs gigantes. + +## Prerequisitos + +Ninguno. Todo usa infraestructura existente: +- `AuditCfg` en `internal/config/schema.go` +- `shell/logger/query.go` para leer JSONL +- `pkg/command/builtins.go` para registrar `!metrics` +- `agents/commands.go` para implementar el handler + +## Riesgos + +| Riesgo | Mitigación | +|--------|------------| +| Audit file crece sin límite | Usar el mismo `DailyRotatingWriter` de `shell/logger/` o rotación externa (logrotate) | +| `LogToRoom` falla (room no existe) | Log warning y continuar — audit a archivo no debe fallar por Matrix | +| `!metrics` lento con logs muy grandes | Los JSONL se rotan a 50MB max. Un día normal tiene KB-pocos MB. Aceptable. | +| Audit de `message_received` loguea contenido sensible | El `Detail` solo incluye metadata (sender, room, is_dm), nunca el body del mensaje | diff --git a/dev/issues/README.md b/dev/issues/README.md index 6e7b3f5..c104de5 100644 --- a/dev/issues/README.md +++ b/dev/issues/README.md @@ -45,3 +45,4 @@ afectados y notas de implementacion. | 32 | E2E: verificar skill /create-agent | [0032-e2e-create-agent-skill.md](0032-e2e-create-agent-skill.md) | pendiente | | 33 | Comandos de robots sin prefijo ! | [0033-bot-commands-no-prefix.md](0033-bot-commands-no-prefix.md) | pendiente | | 34 | E2E: verificar skill /create-bot | [0034-e2e-create-bot-skill.md](0034-e2e-create-bot-skill.md) | pendiente | +| 35 | Audit trail + comando !metrics | [0035-audit-trail-metrics.md](0035-audit-trail-metrics.md) | pendiente |