@saulwade/swl-ses 1.7.4 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +196 -196
- package/README.md +578 -578
- package/agentes/auto-evolucion-swl.md +7 -7
- package/agentes/disenador-ui-swl.md +12 -0
- package/agentes/investigador-ux-swl.md +9 -0
- package/agentes/perfilador-usuario-swl.md +2 -2
- package/agentes/ux-disenador-swl.md +6 -0
- package/comandos/swl/evaluar-skill.md +1 -1
- package/comandos/swl/evolucion-estado.md +5 -5
- package/comandos/swl/evolucionar.md +2 -2
- package/comandos/swl/inbox.md +1 -1
- package/comandos/swl/reflect-skills.md +2 -2
- package/comandos/swl/salud.md +1 -1
- package/habilidades/ai-runtime-security/SKILL.md +2 -2
- package/habilidades/auto-evolucion-protocolo/SKILL.md +2 -2
- package/habilidades/benchmark-memoria/SKILL.md +2 -2
- package/habilidades/drift-detection/SKILL.md +3 -3
- package/habilidades/eval-framework/SKILL.md +1 -1
- package/habilidades/guardrail-semantico/SKILL.md +4 -4
- package/habilidades/proceso-ddia-streaming/SKILL.md +4 -4
- package/habilidades/swl-claudemd/SKILL.md +2 -2
- package/habilidades/testing-python/SKILL.md +1 -1
- package/habilidades/tracing-processor/SKILL.md +1 -1
- package/hooks/actualizar-perfil-usuario.js +2 -2
- package/hooks/aiisms-detector.js +2 -2
- package/hooks/auto-evolucion.js +1 -1
- package/hooks/captura-feedback-usuario.js +2 -2
- package/hooks/claudemd-bloat-detector.js +2 -2
- package/hooks/claudemd-duplicacion-detector.js +1 -1
- package/hooks/guardrail-modelo.js +2 -2
- package/hooks/lib/memory-search.js +1 -1
- package/hooks/lib/nudge-tracker.js +1 -1
- package/hooks/metricas-evolucion.js +3 -3
- package/hooks/rotar-audit-auto.js +2 -2
- package/hooks/validar-formato-post-subagente.js +2 -2
- package/hooks/validar-intent-spec.js +1 -1
- package/hooks/validar-planning-paths.js +134 -0
- package/manifiestos/hooks-config.json +20 -11
- package/manifiestos/modulos.json +1352 -1351
- package/manifiestos/planning-paths.json +44 -0
- package/manifiestos/skills-lock.json +1254 -1254
- package/package.json +92 -92
- package/plugin.json +372 -372
- package/reglas/gobernanza.md +1 -1
- package/reglas/memoria-consolidada.md +7 -7
- package/reglas/sin-duplicacion-reglas-globales.md +1 -1
- package/scripts/auditar-agentes-gaps.js +1 -1
- package/scripts/auditar-cobertura-frameworks.js +2 -2
- package/scripts/auditar-skills-gaps.js +2 -2
- package/scripts/benchmark-memoria.js +3 -3
- package/scripts/inferir-herramientas-permitidas.js +1 -1
- package/scripts/instalador.js +48 -0
- package/scripts/lib/dashboard-widgets.js +3 -3
- package/scripts/lib/drift-detector.js +3 -3
- package/scripts/lib/eval-metrics-store.js +3 -3
- package/scripts/lib/gitignore-manifest.js +3 -3
- package/scripts/mcp-server/README.md +1 -1
- package/scripts/mcp-server/telemetry.js +2 -2
- package/scripts/reflect-skills.js +4 -4
- package/scripts/rotar-audit-logs.js +2 -2
- package/scripts/run-skill-evals.js +2 -2
|
@@ -50,7 +50,7 @@ hardGuardrails:
|
|
|
50
50
|
- "Agentes 'evolvable: false' requieren ADR humano explícito antes de cualquier cambio."
|
|
51
51
|
- "@reglas/gobernanza.md § Gate G8 — skills nuevos pasan por _userland/ + score >=70 antes de promover."
|
|
52
52
|
- "Gates G1-G8 son veto: fallo en cualquier gate aborta la evolución, sin override."
|
|
53
|
-
- "@hooks/audit-trail.js — toda evolución registrada en .planning/
|
|
53
|
+
- "@hooks/audit-trail.js — toda evolución registrada en .planning/evolution/evoluciones.jsonl."
|
|
54
54
|
- "Modificaciones a hooks bloqueantes (calidad-pre-commit, escaneo-secretos) requieren HITL."
|
|
55
55
|
fragmentos:
|
|
56
56
|
- _intent-spec
|
|
@@ -91,7 +91,7 @@ ANTES de modificar cualquier agente o skill:
|
|
|
91
91
|
o está en la lista bloqueada (auto-evolucion-swl, red-team-swl, orquestador-swl,
|
|
92
92
|
revisor-seguridad-swl), detente y reporta al usuario. La política completa
|
|
93
93
|
(qué está bloqueado, por qué, y cuándo re-evaluarla) vive en
|
|
94
|
-
`.planning/
|
|
94
|
+
`.planning/evolution/politica-evolvable.md`.
|
|
95
95
|
|
|
96
96
|
**1a. Normalizar el frontmatter** usando `scripts/lib/skill-normalizer.js`:
|
|
97
97
|
```bash
|
|
@@ -149,19 +149,19 @@ campo `data.diagnosis` con la clasificación del fallo dominante:
|
|
|
149
149
|
| `timeout` | Excedió presupuesto de turnos/tiempo | `toolBudget.complex`, `maxTurnos` |
|
|
150
150
|
| `schema_violation` | Output violó schema declarado | `schemas/agent-output-*.schema.json` + template de output |
|
|
151
151
|
| `task_incomplete` | Terminó con scope parcial | Protocolo de cierre, definición de "done" |
|
|
152
|
-
| `unknown` | No clasificable | Leer últimas 3 trazas de `.planning/auto-
|
|
152
|
+
| `unknown` | No clasificable | Leer últimas 3 trazas de `.planning/auto-evolution/agentes.jsonl` |
|
|
153
153
|
|
|
154
154
|
### Cómo leer el diagnosis de la sesión actual
|
|
155
155
|
|
|
156
156
|
```bash
|
|
157
157
|
# Últimos nudges con su diagnosis
|
|
158
|
-
tail -20 .planning/
|
|
158
|
+
tail -20 .planning/evolution/nudges.jsonl | node -e "process.stdin.on('data',b=>b.toString().split(/\r?\n/).filter(Boolean).forEach(l=>{try{const j=JSON.parse(l);if(j.kind==='auto-evolucion')console.log(j.target,'->',j.data?.diagnosis?.tipo_fallo);}catch{}}))"
|
|
159
159
|
|
|
160
160
|
# Trazas raw del agente objetivo en los últimos 14 días
|
|
161
161
|
node -e "
|
|
162
162
|
const fs=require('fs');
|
|
163
163
|
const ventana=Date.now()-14*24*3600*1000;
|
|
164
|
-
const lines=fs.readFileSync('.planning/auto-
|
|
164
|
+
const lines=fs.readFileSync('.planning/auto-evolution/agentes.jsonl','utf8').split(/\r?\n/).filter(Boolean);
|
|
165
165
|
for(const l of lines){try{const j=JSON.parse(l);if(j.agente==='TU_TARGET' && Date.parse(j.ts)>=ventana)console.log(j.ts,j.status,j.tipo_fallo||'');}catch{}}"
|
|
166
166
|
```
|
|
167
167
|
|
|
@@ -672,7 +672,7 @@ como período de prueba (regla `gobernanza.md` línea 30). La promoción al core
|
|
|
672
672
|
- Oro (≥80) → promover sin más
|
|
673
673
|
- Plata (≥70) → promover, dejar nota en CHANGELOG: "promovido con badge Plata, mejorar en próxima evolución"
|
|
674
674
|
- Bronce (≥60) → NO promover. Devolver a _userland/ con feedback de qué dimensiones bajan el score.
|
|
675
|
-
- Sin badge (<60)→ NO promover. Documentar en .planning/
|
|
675
|
+
- Sin badge (<60)→ NO promover. Documentar en .planning/evolution/promociones-rechazadas.jsonl
|
|
676
676
|
4. Si badge ≥ Plata: mover archivo a habilidades/<nombre>/SKILL.md, registrar
|
|
677
677
|
en manifiestos/modulos.json, actualizar INVENTARIO.md.
|
|
678
678
|
5. Registrar evento en evoluciones.jsonl con tipo: "promocion-skill" y score.
|
|
@@ -702,7 +702,7 @@ Independientemente de los gates:
|
|
|
702
702
|
|
|
703
703
|
### Registro de evoluciones autónomas
|
|
704
704
|
|
|
705
|
-
Cada evolución autónoma escribe a `.planning/
|
|
705
|
+
Cada evolución autónoma escribe a `.planning/evolution/evoluciones.jsonl`:
|
|
706
706
|
|
|
707
707
|
```json
|
|
708
708
|
{"ts":"2026-04-19T...","tipo":"aplicada","target":"skill-x","score":85,"modo":"autonomo"}
|
|
@@ -61,6 +61,18 @@ Responsabilidades concretas:
|
|
|
61
61
|
- Adaptar o extender design systems existentes (Material, Ant, shadcn, Radix)
|
|
62
62
|
- Producir UI-SPEC.md que el implementador pueda seguir sin consultar al diseñador
|
|
63
63
|
|
|
64
|
+
## Path de output canónico (OBLIGATORIO)
|
|
65
|
+
|
|
66
|
+
Escribe TODOS tus artefactos en `.planning/design/` — NUNCA en la raíz del
|
|
67
|
+
proyecto ni en directorios ad-hoc (`ux/`, `diseno/`, `diseno-visual/`):
|
|
68
|
+
|
|
69
|
+
- `.planning/design/UI-SPEC.md` — la especificación visual principal.
|
|
70
|
+
- `.planning/design/tokens.md`, `component-inventory.md`, etc. — artefactos de apoyo.
|
|
71
|
+
|
|
72
|
+
El path está pineado (ADR-0031, `manifiestos/planning-paths.json`): no es elección
|
|
73
|
+
del orquestador. Si ya existe `.planning/design/UI-SPEC.md`, léelo antes de
|
|
74
|
+
sobreescribir. Cierra DT-PLANNING-OUTPUT-PATHS.
|
|
75
|
+
|
|
64
76
|
## Protocolo obligatorio al iniciar
|
|
65
77
|
|
|
66
78
|
ANTES de definir cualquier valor visual:
|
|
@@ -59,6 +59,15 @@ Responsabilidades concretas:
|
|
|
59
59
|
- Analizar datos de uso: heatmaps, funnels, tasas de conversión, bounce rates
|
|
60
60
|
- Producir reportes de investigación accionables con hallazgos y recomendaciones
|
|
61
61
|
|
|
62
|
+
## Path de output canónico (OBLIGATORIO)
|
|
63
|
+
|
|
64
|
+
Escribe TODOS tus artefactos de investigación en `.planning/design/` (reportes,
|
|
65
|
+
personas, customer journeys, análisis heurístico) — NUNCA en la raíz ni en
|
|
66
|
+
`ux/`/`investigacion/`/`research/`. Path pineado (ADR-0031,
|
|
67
|
+
`manifiestos/planning-paths.json`): compartes directorio con `disenador-ui-swl`
|
|
68
|
+
y `ux-disenador-swl` para que el conocimiento de usuario y la spec visual vivan
|
|
69
|
+
juntos. Cierra DT-PLANNING-OUTPUT-PATHS.
|
|
70
|
+
|
|
62
71
|
## Protocolo obligatorio al iniciar
|
|
63
72
|
|
|
64
73
|
ANTES de comenzar cualquier investigación:
|
|
@@ -94,7 +94,7 @@ tercero (perfil del usuario). **No cruces los carriles:**
|
|
|
94
94
|
|
|
95
95
|
3. **Verificar el dirty-bit del hook:**
|
|
96
96
|
```
|
|
97
|
-
Read(".planning/
|
|
97
|
+
Read(".planning/user-profile/dirty.json")
|
|
98
98
|
```
|
|
99
99
|
Este archivo lista las señales acumuladas desde la última consolidación.
|
|
100
100
|
Si no existe: no hay trabajo pendiente; termina con "perfil al día".
|
|
@@ -254,7 +254,7 @@ atomicWriteSync('instintos/perfil-usuario.yaml', yamlContent);
|
|
|
254
254
|
### Paso 6 — Limpiar dirty-bit
|
|
255
255
|
|
|
256
256
|
```bash
|
|
257
|
-
rm -f .planning/
|
|
257
|
+
rm -f .planning/user-profile/dirty.json
|
|
258
258
|
```
|
|
259
259
|
|
|
260
260
|
### Paso 7 — Reportar al usuario
|
|
@@ -43,6 +43,12 @@ realmente pueden usar — no solo interfaces que se ven bien en un mockup.
|
|
|
43
43
|
Tu output es la UI-SPEC.md: el contrato de diseño que el frontend-swl implementará.
|
|
44
44
|
No escribes código. Diseñas con palabras, estructuras y especificaciones precisas.
|
|
45
45
|
|
|
46
|
+
**Path de output canónico (OBLIGATORIO):** escribe TODOS tus artefactos en
|
|
47
|
+
`.planning/design/` (`UI-SPEC.md`, wireframes, flujos) — NUNCA en la raíz ni en
|
|
48
|
+
`ux/`/`diseno/`/`diseno-visual/`. Path pineado (ADR-0031,
|
|
49
|
+
`manifiestos/planning-paths.json`); si ya existe `.planning/design/UI-SPEC.md`,
|
|
50
|
+
léelo antes de sobreescribir. Cierra DT-PLANNING-OUTPUT-PATHS.
|
|
51
|
+
|
|
46
52
|
## Rol y responsabilidad
|
|
47
53
|
|
|
48
54
|
Responsabilidades concretas:
|
|
@@ -369,7 +369,7 @@ Umbral de promoción:
|
|
|
369
369
|
|-------|-------------------------|
|
|
370
370
|
| Platino, Oro, Plata | Promover a `habilidades/`, registrar en manifiestos |
|
|
371
371
|
| Bronce | NO promover, devolver a `_userland/` con feedback |
|
|
372
|
-
| Sin badge | NO promover, registrar rechazo en `.planning/
|
|
372
|
+
| Sin badge | NO promover, registrar rechazo en `.planning/evolution/promociones-rechazadas.jsonl` |
|
|
373
373
|
|
|
374
374
|
Si un skill es rechazado ≥3 veces consecutivas, el agente escala al usuario
|
|
375
375
|
con análisis de qué dimensiones bajan el score. Origen: ADR 0013 sección 3C.
|
|
@@ -31,7 +31,7 @@ PATH="/c/Program Files/nodejs:/c/Program Files (x86)/nodejs:$PATH" echo '{}' | n
|
|
|
31
31
|
## Paso 1 — Cargar métricas
|
|
32
32
|
|
|
33
33
|
```bash
|
|
34
|
-
cat .planning/
|
|
34
|
+
cat .planning/evolution/metricas.json
|
|
35
35
|
```
|
|
36
36
|
|
|
37
37
|
Si el archivo no existe: ejecutar el regenerado del Paso 0. Si sigue sin
|
|
@@ -58,7 +58,7 @@ echo "RATIO=\"$EVOL_FALSE/$TOTAL\""
|
|
|
58
58
|
|
|
59
59
|
Estos valores alimentan la sección KERNEL del template.
|
|
60
60
|
|
|
61
|
-
Si `.planning/
|
|
61
|
+
Si `.planning/evolution/politica-evolvable.md` no existe, reportar como
|
|
62
62
|
hallazgo crítico: el kernel SIN política documentada es violación de
|
|
63
63
|
`reglas/gobernanza.md`.
|
|
64
64
|
|
|
@@ -127,7 +127,7 @@ Template de salida:
|
|
|
127
127
|
...
|
|
128
128
|
|
|
129
129
|
KERNEL (gobernanza)
|
|
130
|
-
Política evolvable .... .planning/
|
|
130
|
+
Política evolvable .... .planning/evolution/politica-evolvable.md
|
|
131
131
|
Último ADR kernel ..... <ADR-NNNN — título — fecha>
|
|
132
132
|
Agentes evolvable=false <n>/<total>
|
|
133
133
|
|
|
@@ -152,7 +152,7 @@ Al final del dashboard, sugerir acciones según las métricas:
|
|
|
152
152
|
→ `npx -y @saulwade/swl-ses@latest bootstrap-instincts` (pobla desde APRENDIZAJES.md)
|
|
153
153
|
|
|
154
154
|
- Si `nudges.tasaAccion < 0.3` y `nudges.total > 5`:
|
|
155
|
-
→ "Muchos nudges ignorados. Revisa `.planning/
|
|
155
|
+
→ "Muchos nudges ignorados. Revisa `.planning/evolution/alertas-persistentes.json`"
|
|
156
156
|
|
|
157
157
|
- Si `alertasActivas.length > 0`:
|
|
158
158
|
→ listar cada alerta con `/swl:evolucionar <target>` o cmd correspondiente
|
|
@@ -178,7 +178,7 @@ Al final del dashboard, sugerir acciones según las métricas:
|
|
|
178
178
|
|
|
179
179
|
## Anti-substitution guardrails
|
|
180
180
|
|
|
181
|
-
- Archivo de métricas: **siempre** `.planning/
|
|
181
|
+
- Archivo de métricas: **siempre** `.planning/evolution/metricas.json` (nunca `.planning/metricas.json`, `evolucion.json`, `estado-evolucion.json`).
|
|
182
182
|
- Hook que regenera: **siempre** `hooks/metricas-evolucion.js` (nunca `metrics.js`, `evolucion-metricas.js`, `evolution-metrics.js`).
|
|
183
183
|
- Para forzar regen: pipe `echo '{}' | node ...`, nunca invocar `require()` directo.
|
|
184
184
|
|
|
@@ -23,7 +23,7 @@ SWL tiene **tres canales independientes** de aprendizaje. Son complementarios, n
|
|
|
23
23
|
### Cómo se coordinan
|
|
24
24
|
|
|
25
25
|
- **Evolución + perfil**: el parser de fricción (`auto-evolucion-protocolo` v1.1) cruza el log
|
|
26
|
-
`.planning/auto-
|
|
26
|
+
`.planning/auto-evolution/agentes.jsonl` con las señales de corrección del usuario
|
|
27
27
|
para priorizar agentes cuyos runs coincidieron con correcciones. Ver tabla
|
|
28
28
|
"Categorías de fricción" en el skill.
|
|
29
29
|
- **Evolución + aprendizajes**: antes de modificar un skill, leer `APRENDIZAJES.md`
|
|
@@ -214,7 +214,7 @@ score_after = (evals_pass / evals_total) * 100 × factor_peso
|
|
|
214
214
|
| `score_after < score_baseline - 5` | **Revertir** — restaurar el archivo anterior + `--record-revert --score=<N>` |
|
|
215
215
|
| `score_baseline - 5 <= score_after < score_baseline` | **Requiere revisión humana** — reportar diferencia; usuario decide si acepta la regresión menor o revierte |
|
|
216
216
|
|
|
217
|
-
Los 3 casos registran evento en `.planning/
|
|
217
|
+
Los 3 casos registran evento en `.planning/evolution/evoluciones.jsonl` para el
|
|
218
218
|
dashboard `/swl:evolucion-estado`.
|
|
219
219
|
|
|
220
220
|
### Regla de oro
|
package/comandos/swl/inbox.md
CHANGED
|
@@ -45,7 +45,7 @@ Por cada comando en la cola, decidir:
|
|
|
45
45
|
| Instrucción de trabajo clara ("arregla el bug X", "ejecuta pruebas") | Procesar como prompt del usuario. Ejecutar la tarea siguiendo el flujo normal SWL. |
|
|
46
46
|
| Slash command (`/swl:salud`, `/swl:metricas`, etc.) | Invocar ese comando directamente. |
|
|
47
47
|
| Pregunta/consulta ("¿cómo va X?", "estado del release") | Responder con la información solicitada. Enviar respuesta al gateway si aplica. |
|
|
48
|
-
| Feedback/corrección ("no uses Y", "prefiero Z") | Escribir a `.planning/
|
|
48
|
+
| Feedback/corrección ("no uses Y", "prefiero Z") | Escribir a `.planning/evolution/feedback-queue.jsonl` con tipo correspondiente y marcar como procesado. |
|
|
49
49
|
| Contenido ambiguo o sospechoso | Marcar como descartado con razón registrada. |
|
|
50
50
|
|
|
51
51
|
### Paso 3 — Procesar y marcar
|
|
@@ -6,7 +6,7 @@ allowed_tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"]
|
|
|
6
6
|
|
|
7
7
|
# /swl:reflect-skills — Descubrimiento de skills emergentes
|
|
8
8
|
|
|
9
|
-
Analiza los archivos JSONL del historial de Claude Code (`~/.claude/projects/<proyecto>/*.jsonl`) y la cola de feedback del usuario (`.planning/
|
|
9
|
+
Analiza los archivos JSONL del historial de Claude Code (`~/.claude/projects/<proyecto>/*.jsonl`) y la cola de feedback del usuario (`.planning/evolution/feedback-queue.jsonl`) para detectar intenciones repetidas que podrían formalizarse como skills, comandos o agentes nuevos del sistema SWL.
|
|
10
10
|
|
|
11
11
|
Complementa a `/swl:aprender` (que trabaja sobre la sesión actual) y a `/swl:evolucionar` (que opera sobre metadatos de agentes/skills existentes). Este comando mira el **historial acumulado** y propone componentes emergentes basándose en la frecuencia real de uso.
|
|
12
12
|
|
|
@@ -41,7 +41,7 @@ Parámetros:
|
|
|
41
41
|
|
|
42
42
|
El script produce:
|
|
43
43
|
- Reporte textual en stdout
|
|
44
|
-
- Archivo estructurado en `.planning/
|
|
44
|
+
- Archivo estructurado en `.planning/evolution/reflect-skills-report.json`
|
|
45
45
|
|
|
46
46
|
### Paso 2 — Leer y clasificar los candidatos
|
|
47
47
|
|
package/comandos/swl/salud.md
CHANGED
|
@@ -290,7 +290,7 @@ SWL_AUDIT_FRAMEWORKS=1 npx -y @saulwade/swl-ses@latest audit-coverage-frameworks
|
|
|
290
290
|
npx -y @saulwade/swl-ses@latest audit-coverage-frameworks --save
|
|
291
291
|
```
|
|
292
292
|
|
|
293
|
-
Persiste en `.planning/
|
|
293
|
+
Persiste en `.planning/evolution/cobertura-frameworks.json` para comparación
|
|
294
294
|
histórica tras incorporar nuevos skills de seguridad.
|
|
295
295
|
|
|
296
296
|
Si `SWL_AUDIT_FRAMEWORKS` no está definida, este paso se omite sin mensaje
|
|
@@ -123,12 +123,12 @@ Checklist para cualquier aplicación LLM en producción:
|
|
|
123
123
|
- [ ] Canary token en system prompt + validación en output (capa 2)
|
|
124
124
|
- [ ] Tool whitelist por agente documentada en frontmatter (capa 3)
|
|
125
125
|
- [ ] Confirmación humana para acciones irreversibles (capa 3)
|
|
126
|
-
- [ ] Logs de intentos detectados en `.planning/auto-
|
|
126
|
+
- [ ] Logs de intentos detectados en `.planning/auto-evolution/agentes.jsonl` con campo `tipo_fallo: prompt_injection`
|
|
127
127
|
|
|
128
128
|
## Gotchas / Errores comunes no obvios
|
|
129
129
|
|
|
130
130
|
- **Confiar solo en regex**: los atacantes reescriben payloads trivialmente (sinónimos, ofuscación base64, division de strings, caracteres Unicode similares). Causa: las firmas son conocidas y públicas; cualquier evasión simple las burla. Solución: combinar siempre capa 1 con capa 2 + capa 3; nunca tratar la detección de la capa 1 como suficiente. Si el regex pasa pero el heurístico marca anomalía estructural, escalar a clasificador o a humano.
|
|
131
|
-
- **Ignorar indirect injection porque "los usuarios son confiables"**: el input legítimo del usuario puede contener contenido externo no confiable (URL que se fetchea, archivo subido, documento RAG). Causa: el autor del payload no es quien interactúa — es quien puso el contenido en la ruta del agente. Solución: tratar
|
|
131
|
+
- **Ignorar indirect injection porque "los usuarios son confiables"**: el input legítimo del usuario puede contener contenido externo no confiable (URL que se fetchea, archivo subido, documento RAG). Causa: el autor del payload no es quien interactúa — es quien puso el contenido en la ruta del agente. Solución: tratar todo el contenido externo como datos, nunca como instrucciones; auditar especialmente ingesta de URLs, fetching de páginas web, y documentos en pipelines RAG.
|
|
132
132
|
- **Tratar el clasificador como oráculo binario**: `protectai/deberta-v3-base-prompt-injection-v2` es un modelo, no una verdad absoluta. Tiene falsos positivos y falsos negativos. Causa: los clasificadores son entrenados con datasets específicos; inputs legítimos de dominios no representados en el training pueden marcarse. Solución: usar el score como una señal entre varias, no como veredicto; calibrar el umbral contra un dataset propio de inputs legítimos antes de desplegar.
|
|
133
133
|
- **Canary tokens estáticos en el código**: incluir el mismo canary en repo público o en logs permite al atacante conocerlo y evitar filtrarlo. Causa: si el canary es predecible, el atacante lo filtra del output antes de devolverlo. Solución: generar canary por sesión o por deploy, nunca hardcodeado en el repo visible; rotarlo al menos por release.
|
|
134
134
|
- **Confiar en el frontmatter `tools:` del agente como único control**: el frontmatter es declaración leída por Claude Code, pero un agente con `tools: [Read]` todavía puede pedir `Bash` en su output y el runtime podría ejecutarlo si no hay enforcement. Causa: pre-aprobación ≠ restricción real. Solución: verificar que el permission mode de Claude Code o los hooks PreToolUse enforsan la restricción; no confiar solo en la declaración.
|
|
@@ -194,7 +194,7 @@ ver [recursos/referencia-completa.md](recursos/referencia-completa.md).
|
|
|
194
194
|
## Parser de señales de fricción (v1.1)
|
|
195
195
|
|
|
196
196
|
El hook `hooks/auto-evolucion.js` (SubagentStop) alimenta el log
|
|
197
|
-
`.planning/auto-
|
|
197
|
+
`.planning/auto-evolution/agentes.jsonl` y emite *nudges* hacia
|
|
198
198
|
`auto-evolucion-swl` cuando detecta umbrales cruzados. Este skill define
|
|
199
199
|
**qué cuenta como fricción** para que el agente tenga criterio uniforme al
|
|
200
200
|
interpretar el log.
|
|
@@ -233,7 +233,7 @@ Al invocar `auto-evolucion-swl` o `/swl:evolucionar <agente>`:
|
|
|
233
233
|
|
|
234
234
|
1. **Leer el log filtrado por agente:**
|
|
235
235
|
```bash
|
|
236
|
-
grep "\"agente\":\"<nombre>\"" .planning/auto-
|
|
236
|
+
grep "\"agente\":\"<nombre>\"" .planning/auto-evolution/agentes.jsonl | tail -50
|
|
237
237
|
```
|
|
238
238
|
|
|
239
239
|
2. **Cuantificar las 6 categorías** (fallo duro, run vacío, trivial recurrente,
|
|
@@ -122,7 +122,7 @@ node scripts/benchmark-memoria.js --verbose
|
|
|
122
122
|
### Tracking histórico opcional
|
|
123
123
|
|
|
124
124
|
Si se setea `SWL_BENCHMARK_PERSIST=1`, el benchmark escribe el resumen
|
|
125
|
-
agregado a `.planning/
|
|
125
|
+
agregado a `.planning/evolution/benchmark-memoria.jsonl` (append-only)
|
|
126
126
|
para detectar regresión entre releases:
|
|
127
127
|
|
|
128
128
|
```bash
|
|
@@ -131,7 +131,7 @@ SWL_BENCHMARK_PERSIST=1 node scripts/benchmark-memoria.js
|
|
|
131
131
|
|
|
132
132
|
Comparar entre releases:
|
|
133
133
|
```bash
|
|
134
|
-
tail -5 .planning/
|
|
134
|
+
tail -5 .planning/evolution/benchmark-memoria.jsonl | jq -c '{ts: .timestamp, r5: .promedio.recall_at_5}'
|
|
135
135
|
```
|
|
136
136
|
|
|
137
137
|
---
|
|
@@ -135,7 +135,7 @@ const resultado = ejecutarDriftReflect(
|
|
|
135
135
|
```
|
|
136
136
|
|
|
137
137
|
Cuando `estado_global === 'critico'`, el módulo emite automáticamente un nudge
|
|
138
|
-
a `.planning/
|
|
138
|
+
a `.planning/evolution/nudges.jsonl`:
|
|
139
139
|
|
|
140
140
|
```json
|
|
141
141
|
{
|
|
@@ -167,7 +167,7 @@ El agente `auto-evolucion-swl` consume estos nudges para proponer mejoras.
|
|
|
167
167
|
|
|
168
168
|
- **Timestamps inválidos en eventos JSONL provocan líneas ignoradas silenciosamente**: el módulo es permisivo con los campos pero si ningún campo de timestamp (`timestamp`, `ts`, `inicio`, `created_at`) tiene una fecha ISO válida, el evento se descarta del cálculo. Causa: eventos generados con timestamps de formato local (ej. `"19/04/2026"`) no pasan la validación. Solución: verificar que todos los eventos JSONL del trace tengan al menos un campo de timestamp en formato ISO 8601 — si el baseline aparece como 0, es el primer síntoma de eventos descartados.
|
|
169
169
|
- **Estado `critico` emitido por baseline con muy pocos eventos**: si el baseline de 4 semanas tiene solo 3 eventos y la ventana de 7 días tiene 8, el `driftPct` de tokens se dispara al 166% cuando en realidad el agente está más activo, no degradado. Causa: el módulo no valida que el baseline tenga suficientes eventos para ser estadísticamente válido. Solución: antes de interpretar un estado `critico`, verificar que el baseline tiene al menos 20 eventos — si no, marcar el resultado como `insufficient-data` en lugar de accionar.
|
|
170
|
-
- **Nudge duplicado en `.planning/
|
|
170
|
+
- **Nudge duplicado en `.planning/evolution/nudges.jsonl` por falta de deduplicación**: el hook se ejecuta dos veces en el mismo `SubagentStop` (por bug de throttle) y emite el mismo nudge dos veces. Causa: el throttle `SWL_DRIFT_THROTTLE_H` no validó correctamente el timestamp del último run. Solución: el archivo `nudges.jsonl` es append-only — antes de emitir un nudge, verificar si el último evento del mismo `agente_o_skill` y `metrica` tiene un timestamp dentro de la ventana de throttle.
|
|
171
171
|
- **`atomicWriteJSON` usado para escribir en nudges.jsonl**: escribir el archivo completo en lugar de hacer append corrompe el historial de nudges previos. Causa: confusión entre archivos de estado mutable (usan `atomicWriteJSON`) y archivos de eventos de alta frecuencia (usan `fs.appendFileSync`). Solución: `nudges.jsonl` es un JSONL de alta frecuencia — siempre usar `fs.appendFileSync(ruta, JSON.stringify(nudge) + '\n')`, nunca reescribir el archivo completo.
|
|
172
172
|
|
|
173
173
|
## Referencia cruzada
|
|
@@ -175,5 +175,5 @@ El agente `auto-evolucion-swl` consume estos nudges para proponer mejoras.
|
|
|
175
175
|
- Módulo: `scripts/lib/drift-detector.js`
|
|
176
176
|
- Tests: `tests/lib/drift-detector.test.js`
|
|
177
177
|
- Operador Reflect: `hooks/lib/reflect-classifier.js`
|
|
178
|
-
- Ciclo AGP: `.planning/
|
|
178
|
+
- Ciclo AGP: `.planning/evolution/nudges.jsonl`
|
|
179
179
|
- Origen (adaptado de): `temp/mission-control-main/src/lib/agent-evals.ts` — MIT
|
|
@@ -24,7 +24,7 @@ evolvable: true # default para skill estandar
|
|
|
24
24
|
resultado de búsqueda) cuando se quiera puntuar su calidad antes de
|
|
25
25
|
persistir.
|
|
26
26
|
- Para auditar histórico de calidad de una función crítica (ver métricas
|
|
27
|
-
agregadas en `.planning/
|
|
27
|
+
agregadas en `.planning/evolution/eval-metrics.json`).
|
|
28
28
|
- En tests/CI cuando el contrato del output tenga campos obligatorios y
|
|
29
29
|
quality thresholds.
|
|
30
30
|
- En loops de auto-corrección donde un output inválido debe regenerarse
|
|
@@ -38,7 +38,7 @@ si se justifica el costo del modelo seleccionado.
|
|
|
38
38
|
- Al diseñar hooks `PreToolUse` que evalúan prompts antes de invocar un subagente.
|
|
39
39
|
- Al implementar degradación de modelo basada en complejidad de tarea.
|
|
40
40
|
- Al revisar si `guardrail-modelo.js` necesita nuevos criterios de tripwire.
|
|
41
|
-
- Al analizar logs de `.planning/
|
|
41
|
+
- Al analizar logs de `.planning/evolution/guardrail-observaciones.jsonl`.
|
|
42
42
|
|
|
43
43
|
---
|
|
44
44
|
|
|
@@ -199,7 +199,7 @@ Pasar de modo `observational` a `blocking` sin revisar las observaciones acumula
|
|
|
199
199
|
es una fuente garantizada de falsos positivos. El ciclo correcto:
|
|
200
200
|
|
|
201
201
|
1. Deploy en modo `observational` (exit 0 siempre).
|
|
202
|
-
2. Revisar `.planning/
|
|
202
|
+
2. Revisar `.planning/evolution/guardrail-observaciones.jsonl` tras ≥50 activaciones.
|
|
203
203
|
3. Calcular tasa de falsos positivos. Si < 5%, considerar `run_in_parallel`.
|
|
204
204
|
4. Solo con tasa < 2% y aprobación manual, activar `blocking`.
|
|
205
205
|
|
|
@@ -240,14 +240,14 @@ if (tripwire) {
|
|
|
240
240
|
process.stderr.write(
|
|
241
241
|
`[guardrail-modelo] El agente '${agenteNombre}' podría ejecutarse con 'haiku' ` +
|
|
242
242
|
`(menos costoso). Razón: prompt corto sin keywords críticas (${prompt.length} chars). ` +
|
|
243
|
-
`Ver .planning/
|
|
243
|
+
`Ver .planning/evolution/guardrail-observaciones.jsonl\n`
|
|
244
244
|
);
|
|
245
245
|
}
|
|
246
246
|
// exit 0 siempre — modo observacional
|
|
247
247
|
process.exit(0);
|
|
248
248
|
```
|
|
249
249
|
|
|
250
|
-
**Evento JSONL resultante** en `.planning/
|
|
250
|
+
**Evento JSONL resultante** en `.planning/evolution/guardrail-observaciones.jsonl`:
|
|
251
251
|
|
|
252
252
|
```jsonl
|
|
253
253
|
{"timestamp":"2026-04-19T14:23:01.000Z","agente":"notificador-swl","modelo_actual":"sonnet","modelo_sugerido":"haiku","razon_tripwire":"prompt-corto-sin-keywords-criticas","prompt_length":87}
|
|
@@ -22,7 +22,7 @@ streams locales. Los patrones del Cap 11 aplican directamente.
|
|
|
22
22
|
## Cuándo cargar
|
|
23
23
|
|
|
24
24
|
- Crear un hook que persiste eventos en JSONL (telemetría, audit, evolución).
|
|
25
|
-
- Diseñar un consumidor de `.planning/
|
|
25
|
+
- Diseñar un consumidor de `.planning/evolution/*.jsonl`,
|
|
26
26
|
`.planning/audit.jsonl`, `.planning/comms/nudges.jsonl`.
|
|
27
27
|
- Diagnosticar duplicación de eventos en JSONL.
|
|
28
28
|
- Decidir si un hook debe ser idempotente o si basta con append.
|
|
@@ -80,9 +80,9 @@ fuente).
|
|
|
80
80
|
|
|
81
81
|
| Archivo | Productor | Consumidores | ¿Es event source? |
|
|
82
82
|
|---|---|---|---|
|
|
83
|
-
| `.planning/
|
|
84
|
-
| `.planning/
|
|
85
|
-
| `.planning/
|
|
83
|
+
| `.planning/evolution/evoluciones.jsonl` | `/swl:evolucionar`, hook `evolucion-detector` | `/swl:evolucion-estado`, dashboard | Sí |
|
|
84
|
+
| `.planning/evolution/nudges.jsonl` | hooks varios | `/swl:salud`, `red-team-swl` | Sí |
|
|
85
|
+
| `.planning/evolution/agentes.jsonl` | hook `telemetria-agentes` | `/swl:metricas` | Sí |
|
|
86
86
|
| `.planning/audit.jsonl` | hook `audit-trail` | auditorías, post-mortems | Sí (con Merkle) |
|
|
87
87
|
| `.planning/comms/*.jsonl` | `notificador-swl` | inbox, gateway | Sí |
|
|
88
88
|
|
|
@@ -279,7 +279,7 @@ El sistema tiene dos capas de protección complementarias:
|
|
|
279
279
|
| Capa | Mecanismo | Cuándo actúa | Bloqueo |
|
|
280
280
|
|------|-----------|--------------|---------|
|
|
281
281
|
| Síncrona | Paso 6.5 de `/swl:aprender` (y equivalente en otros comandos) | Justo después del Write/Edit, antes del reporte final | Bloquea pasos posteriores hasta resolver |
|
|
282
|
-
| Asíncrona | Hook `claudemd-bloat-detector.js` (PostToolUse) | Tras cualquier Write/Edit/MultiEdit a CLAUDE.md (incluso fuera de comandos SWL) | No bloquea — emite nudge a `.planning/
|
|
282
|
+
| Asíncrona | Hook `claudemd-bloat-detector.js` (PostToolUse) | Tras cualquier Write/Edit/MultiEdit a CLAUDE.md (incluso fuera de comandos SWL) | No bloquea — emite nudge a `.planning/evolution/nudges.jsonl` |
|
|
283
283
|
|
|
284
284
|
La capa síncrona es proactiva (detiene el comando antes de reportar
|
|
285
285
|
éxito). La asíncrona es retroactiva (cubre escrituras desde fuera de
|
|
@@ -370,7 +370,7 @@ Reglas incluidas en v1.7.0:
|
|
|
370
370
|
|
|
371
371
|
`hooks/claudemd-duplicacion-detector.js` (PostToolUse, no bloquea)
|
|
372
372
|
ejecuta el detector tras cualquier Write/Edit a CLAUDE.md y emite
|
|
373
|
-
nudge a `.planning/
|
|
373
|
+
nudge a `.planning/evolution/nudges.jsonl` con `kind:
|
|
374
374
|
claudemd-duplicacion-reglas`. Opt-out: `SWL_CLAUDEMD_DUPLICACION=0`.
|
|
375
375
|
|
|
376
376
|
### Cómo refactorizar duplicaciones detectadas
|
|
@@ -221,7 +221,7 @@ Para ejemplos detallados MAL vs BIEN de anti-patrones, ver [recursos/ejemplos-co
|
|
|
221
221
|
- **`mock.patch` parcheado en el módulo de tests en lugar de en el módulo que lo usa**: el mock no tiene efecto porque la función ya fue importada en el módulo objetivo antes del patch. Causa: `mock.patch("tests.test_factura.calcular_iva")` parchea la referencia en el módulo de tests, pero `factura_service.py` ya importó `calcular_iva` directamente y sigue usando la original. Solución: patchear siempre en el lugar donde se usa la función: `mock.patch("factura_service.calcular_iva")` — el destino del patch debe ser la ruta del módulo que importó la función, no donde está definida.
|
|
222
222
|
- **`pytest-asyncio` marca el test como `async def` y pasa, pero el `await` dentro no se ejecuta**: el test parece correr sin errores pero la coroutine interna nunca se ejecuta. Causa: sin `@pytest.mark.asyncio` o sin `asyncio_mode = "auto"` en pytest.ini, pytest ejecuta la función async como síncrona — la coroutine se crea y se descarta sin ejecutar. Solución: agregar `@pytest.mark.asyncio` al test o configurar `asyncio_mode = "auto"` en `pytest.ini`; verificar con `pytest --tb=short -v` que el test no termina instantáneamente.
|
|
223
223
|
- **Factory Boy `SubFactory` genera objetos nuevos en cada test aunque el fixture del objeto padre ya existe**: la factory crea una instancia nueva del modelo relacionado en la BD aunque ya exista el objeto padre en el test. Causa: `factory.SubFactory(ClienteFactory)` siempre instancia un nuevo `Cliente` — no reutiliza el fixture del test. Solución: pasar el objeto padre existente al instanciar la factory: `FacturaFactory(cliente=cliente_existente)` — la factory sobreescribe el campo `cliente` con el objeto ya creado en lugar de crear uno nuevo.
|
|
224
|
-
- **`os.chdir()` (Python) o `process.chdir()` (Node) en tests no afecta módulos cargados con paths relativos basados en `__dirname`/`__file__`**: si un módulo calcula su ruta de datos al cargar con `path.resolve(__dirname, ...)` o `Path(__file__).parent`, los tests no pueden redirigir esa ruta cambiando el cwd — el path se evaluó al `require`/`import` y queda fijado. Caso real: test que cambia `process.chdir(tmpDir)` antes de llamar funciones que escriben a `.planning/
|
|
224
|
+
- **`os.chdir()` (Python) o `process.chdir()` (Node) en tests no afecta módulos cargados con paths relativos basados en `__dirname`/`__file__`**: si un módulo calcula su ruta de datos al cargar con `path.resolve(__dirname, ...)` o `Path(__file__).parent`, los tests no pueden redirigir esa ruta cambiando el cwd — el path se evaluó al `require`/`import` y queda fijado. Caso real: test que cambia `process.chdir(tmpDir)` antes de llamar funciones que escriben a `.planning/evolution/nudges.jsonl` pero `RUTA_NUDGES = path.resolve(__dirname, '..', '..', '.planning', ...)` apunta al proyecto real. Solución: dos opciones: (1) test de integración con backup/restore del archivo real (más simple cuando son pocos tests), o (2) refactor del módulo para aceptar override de ruta vía parámetro o variable de entorno (preferible si el módulo es muy testeable). Aplica también a Python con `pathlib.Path(__file__).parent`.
|
|
225
225
|
- **Sanitizar antes de truncar invalida assertions de longitud en tests**: un test que verifica `truncar('a'.repeat(300), 100).length === 100` falla porque `'a'.repeat(300)` matchea la regex de redact `\b[A-Za-z0-9_-]{32,}\b` y la función sanitiza primero produciendo `[REDACTED]` (10 chars) que no se trunca. Causa: el orden `sanitizar → truncar` reduce el texto antes de que truncar opere. Solución en tests: usar fixtures que NO triggeren patrones de redact (ej: texto con espacios cada N chars como `'palabra corta '.repeat(N)`); separar tests de sanitización y truncado en casos disjuntos. NO modificar la función para reordenar — sanitizar antes es correcto en producción.
|
|
226
226
|
|
|
227
227
|
## Refactorizar parsers: fixtures multi-formato ANTES del cambio
|
|
@@ -169,7 +169,7 @@ Endpoint: `JAEGER_OTLP_ENDPOINT` (por defecto `http://localhost:4318/v1/traces`)
|
|
|
169
169
|
|
|
170
170
|
En lugar de persistir spans crudos, un exportador puede agregar en memoria:
|
|
171
171
|
contar spans por tipo, sumar duraciones, detectar anomalías. En `onTraceEnd`
|
|
172
|
-
emite las métricas agregadas a `.planning/
|
|
172
|
+
emite las métricas agregadas a `.planning/evolution/metricas.json` usando
|
|
173
173
|
`atomicWriteJSON` de `hooks/lib/atomic-write.js`.
|
|
174
174
|
|
|
175
175
|
---
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* persistente del usuario (instintos/perfil-usuario.yaml).
|
|
11
11
|
*
|
|
12
12
|
* No modifica el perfil directamente — solo acumula señales en un
|
|
13
|
-
* "dirty-bit" (.planning/
|
|
13
|
+
* "dirty-bit" (.planning/user-profile/dirty.json) y, cuando el umbral
|
|
14
14
|
* se cruza, emite un nudge por stderr sugiriendo invocar el agente
|
|
15
15
|
* perfilador-usuario-swl.
|
|
16
16
|
*
|
|
@@ -60,7 +60,7 @@ try {
|
|
|
60
60
|
// ---------------------------------------------------------------------------
|
|
61
61
|
|
|
62
62
|
const UMBRAL_NUDGE = parseInt(process.env.SWL_PERFIL_UMBRAL || '3', 10);
|
|
63
|
-
const DIR_PERFIL = path.join(process.cwd(), '.planning', '
|
|
63
|
+
const DIR_PERFIL = path.join(process.cwd(), '.planning', 'user-profile');
|
|
64
64
|
const DIRTY_PATH = path.join(DIR_PERFIL, 'dirty.json');
|
|
65
65
|
const PERFIL_PATH = path.join(process.cwd(), 'instintos', 'perfil-usuario.yaml');
|
|
66
66
|
const APRENDIZAJES_PATH = path.join(process.cwd(), '.planning', 'APRENDIZAJES.md');
|
package/hooks/aiisms-detector.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*
|
|
8
8
|
* Ejecuta el detector portable `habilidades/estilo-sin-ai-isms/scripts/detectar_aiisms.py`
|
|
9
9
|
* contra archivos .md recién modificados y emite un nudge a
|
|
10
|
-
* `.planning/
|
|
10
|
+
* `.planning/evolution/nudges.jsonl` si encuentra al menos un AI-ism
|
|
11
11
|
* de severidad P0.
|
|
12
12
|
*
|
|
13
13
|
* Opt-out: SWL_AIISMS_HOOK=0 desactiva completamente el hook.
|
|
@@ -160,7 +160,7 @@ const nudge = {
|
|
|
160
160
|
|
|
161
161
|
// Persistir a nudges.jsonl (JSONL append, no reescribir)
|
|
162
162
|
try {
|
|
163
|
-
const nudgesPath = path.join(CWD, '.planning', '
|
|
163
|
+
const nudgesPath = path.join(CWD, '.planning', 'evolution', 'nudges.jsonl');
|
|
164
164
|
const nudgesDir = path.dirname(nudgesPath);
|
|
165
165
|
if (!fs.existsSync(nudgesDir)) {
|
|
166
166
|
fs.mkdirSync(nudgesDir, { recursive: true });
|
package/hooks/auto-evolucion.js
CHANGED
|
@@ -105,7 +105,7 @@ const VENTANA_DIAS = 14;
|
|
|
105
105
|
const MIN_TOOL_CALLS = 5; // por debajo se considera trivial
|
|
106
106
|
const MIN_INVOCACIONES_LOOP = 6; // mínimo para que el ratio de convergencia sea significativo
|
|
107
107
|
|
|
108
|
-
const DIR_AUTOEVOL = path.join(process.cwd(), '.planning', 'auto-
|
|
108
|
+
const DIR_AUTOEVOL = path.join(process.cwd(), '.planning', 'auto-evolution');
|
|
109
109
|
const DIR_TRACES = path.join(process.cwd(), '.planning', 'traces');
|
|
110
110
|
const LOG_PATH = path.join(DIR_AUTOEVOL, 'agentes.jsonl');
|
|
111
111
|
const NUDGES_PATH = path.join(DIR_AUTOEVOL, 'nudges.json');
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* Tipo: UserPromptSubmit
|
|
7
7
|
*
|
|
8
8
|
* Detecta correcciones explícitas del usuario ("no hagas X", "recuerda Y",
|
|
9
|
-
* "prefiero Z") y las encola en .planning/
|
|
9
|
+
* "prefiero Z") y las encola en .planning/evolution/feedback-queue.jsonl
|
|
10
10
|
* para que el perfilador-usuario-swl, el ciclo AGP y /swl:aprender puedan
|
|
11
11
|
* consumirlas sin depender de que el usuario ejecute comandos manualmente.
|
|
12
12
|
*
|
|
@@ -104,7 +104,7 @@ function detectarFeedback(prompt) {
|
|
|
104
104
|
*/
|
|
105
105
|
function encolar(hallazgo, meta) {
|
|
106
106
|
try {
|
|
107
|
-
const dir = path.join(process.cwd(), '.planning', '
|
|
107
|
+
const dir = path.join(process.cwd(), '.planning', 'evolution');
|
|
108
108
|
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
109
109
|
|
|
110
110
|
const entrada = {
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* Tipo: PostToolUse (aplica a: Write, Edit, MultiEdit)
|
|
7
7
|
*
|
|
8
8
|
* Ejecuta `scripts/auditar-claudemd.js` contra archivos `CLAUDE.md`
|
|
9
|
-
* recién modificados y emite un nudge a `.planning/
|
|
9
|
+
* recién modificados y emite un nudge a `.planning/evolution/nudges.jsonl`
|
|
10
10
|
* si el veredicto es WARN o ERROR.
|
|
11
11
|
*
|
|
12
12
|
* Aplica ADR-0016 (best practices Anthropic "The CLAUDE.md file"):
|
|
@@ -148,7 +148,7 @@ const nudge = {
|
|
|
148
148
|
|
|
149
149
|
// ─── Persistir a nudges.jsonl ─────────────────────────────────────────────
|
|
150
150
|
try {
|
|
151
|
-
const nudgesPath = path.join(CWD, '.planning', '
|
|
151
|
+
const nudgesPath = path.join(CWD, '.planning', 'evolution', 'nudges.jsonl');
|
|
152
152
|
const nudgesDir = path.dirname(nudgesPath);
|
|
153
153
|
if (!fs.existsSync(nudgesDir)) {
|
|
154
154
|
fs.mkdirSync(nudgesDir, { recursive: true });
|
|
@@ -157,7 +157,7 @@ const nudge = {
|
|
|
157
157
|
|
|
158
158
|
// ─── Persistir a nudges.jsonl ─────────────────────────────────────────────
|
|
159
159
|
try {
|
|
160
|
-
const nudgesPath = path.join(CWD, '.planning', '
|
|
160
|
+
const nudgesPath = path.join(CWD, '.planning', 'evolution', 'nudges.jsonl');
|
|
161
161
|
const nudgesDir = path.dirname(nudgesPath);
|
|
162
162
|
if (!fs.existsSync(nudgesDir)) {
|
|
163
163
|
fs.mkdirSync(nudgesDir, { recursive: true });
|
|
@@ -38,7 +38,7 @@ if (!process.env.SWL_GUARDRAIL_MODELO) {
|
|
|
38
38
|
// ---------------------------------------------------------------------------
|
|
39
39
|
|
|
40
40
|
const CWD = process.cwd();
|
|
41
|
-
const DIR_EVOL = path.join(CWD, '.planning', '
|
|
41
|
+
const DIR_EVOL = path.join(CWD, '.planning', 'evolution');
|
|
42
42
|
const GUARDRAIL_LOG = path.join(DIR_EVOL, 'guardrail-observaciones.jsonl');
|
|
43
43
|
|
|
44
44
|
// ---------------------------------------------------------------------------
|
|
@@ -237,7 +237,7 @@ async function main() {
|
|
|
237
237
|
`[guardrail-modelo] El agente '${agenteNombre}' podría ejecutarse con ` +
|
|
238
238
|
`'${evento.modelo_sugerido}' (menos costoso). ` +
|
|
239
239
|
`Razón: ${evento.razon_tripwire}. ` +
|
|
240
|
-
`Ver .planning/
|
|
240
|
+
`Ver .planning/evolution/guardrail-observaciones.jsonl\n`
|
|
241
241
|
);
|
|
242
242
|
|
|
243
243
|
// Modo observacional — exit 0 siempre
|
|
@@ -544,7 +544,7 @@ function fetch(baseDir, id) {
|
|
|
544
544
|
function _logUsage(op, baseDir, query, resultsCount) {
|
|
545
545
|
if (process.env.SWL_MEMORY_TELEMETRY === '0') return;
|
|
546
546
|
try {
|
|
547
|
-
const dir = path.join(baseDir, '.planning', '
|
|
547
|
+
const dir = path.join(baseDir, '.planning', 'evolution');
|
|
548
548
|
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
549
549
|
const entry = {
|
|
550
550
|
ts: new Date().toISOString(),
|
|
@@ -45,7 +45,7 @@ try {
|
|
|
45
45
|
// Configuración
|
|
46
46
|
// ---------------------------------------------------------------------------
|
|
47
47
|
|
|
48
|
-
const DIR_EVOL = path.join(process.cwd(), '.planning', '
|
|
48
|
+
const DIR_EVOL = path.join(process.cwd(), '.planning', 'evolution');
|
|
49
49
|
const LOG_PATH = path.join(DIR_EVOL, 'nudges.jsonl');
|
|
50
50
|
const ALERT_PATH = path.join(DIR_EVOL, 'alertas-persistentes.json');
|
|
51
51
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* Tipo: Stop (async: true — fire-and-forget)
|
|
7
7
|
*
|
|
8
8
|
* Cada sesión consolida métricas del ciclo de evolución y actualiza
|
|
9
|
-
* .planning/
|
|
9
|
+
* .planning/evolution/metricas.json con:
|
|
10
10
|
* - nudges emitidos / accionados / pendientes (14d)
|
|
11
11
|
* - tasa de acción por tipo de nudge
|
|
12
12
|
* - instintos populados vs capacidad
|
|
@@ -37,12 +37,12 @@ try {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
const CWD = process.cwd();
|
|
40
|
-
const DIR_EVOL = path.join(CWD, '.planning', '
|
|
40
|
+
const DIR_EVOL = path.join(CWD, '.planning', 'evolution');
|
|
41
41
|
const METRICAS_PATH = path.join(DIR_EVOL, 'metricas.json');
|
|
42
42
|
const INSTINTOS_PROYECTO = path.join(CWD, 'instintos', 'proyecto.yaml');
|
|
43
43
|
const INSTINTOS_GLOBAL = path.join(CWD, 'instintos', 'global.yaml');
|
|
44
44
|
const INSTINTOS_PERFIL = path.join(CWD, 'instintos', 'perfil-usuario.yaml');
|
|
45
|
-
const AGENTES_LOG = path.join(CWD, '.planning', 'auto-
|
|
45
|
+
const AGENTES_LOG = path.join(CWD, '.planning', 'auto-evolution', 'agentes.jsonl');
|
|
46
46
|
const APRENDIZAJES = path.join(CWD, '.planning', 'APRENDIZAJES.md');
|
|
47
47
|
const EVOLUCIONES_LOG = path.join(DIR_EVOL, 'evoluciones.jsonl');
|
|
48
48
|
const MEMORY_USAGE_LOG = path.join(DIR_EVOL, 'memory-usage.jsonl');
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* Se ejecuta al terminar una respuesta. Verifica si los archivos de auditoría
|
|
9
9
|
* (.planning/audit.jsonl y audit-merkle.jsonl) superan el umbral configurable
|
|
10
10
|
* y, de ser así, invoca scripts/rotar-audit-logs.js para archivar entradas
|
|
11
|
-
* antiguas a .planning/
|
|
11
|
+
* antiguas a .planning/archive/audit/<nombre>-YYYY-MM.jsonl.gz.
|
|
12
12
|
*
|
|
13
13
|
* Política:
|
|
14
14
|
* - Umbral default: 5 MB por archivo (UMBRAL_BYTES). Configurable vía env
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* - Desactivable con SWL_AUDIT_ROTATE_OFF=1 (para CI o escenarios donde
|
|
19
19
|
* la rotación debe ser manual).
|
|
20
20
|
* - Cooldown: no se re-ejecuta si hubo una rotación exitosa en las últimas
|
|
21
|
-
* 6 horas (marca en .planning/
|
|
21
|
+
* 6 horas (marca en .planning/archive/audit/.ultima-rotacion).
|
|
22
22
|
*
|
|
23
23
|
* Resultado:
|
|
24
24
|
* - stdout: 1-2 líneas si se rotó, silencioso si no
|