@saulwade/swl-ses 1.9.0 → 2.0.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 +8 -8
- package/README.md +12 -12
- package/agentes/accesibilidad-wcag-swl.md +3 -3
- package/agentes/auto-evolucion-swl.md +908 -908
- package/agentes/disenador-ui-swl.md +6 -5
- package/agentes/frontend-angular-swl.md +2 -2
- package/agentes/frontend-css-swl.md +2 -2
- package/agentes/frontend-react-swl.md +4 -4
- package/agentes/frontend-swl.md +6 -6
- package/agentes/investigador-ux-swl.md +5 -5
- package/agentes/orquestador-swl.md +7 -7
- package/agentes/perfilador-usuario-swl.md +308 -308
- package/agentes/producto-prd-swl.md +1 -1
- package/agentes/red-team-swl.md +218 -218
- package/agentes/tdd-qa-swl.md +17 -1
- package/comandos/swl/actualizar.md +1 -1
- package/comandos/swl/aprender.md +2 -2
- package/comandos/swl/aprobar-plan.md +152 -0
- package/comandos/swl/ayuda.md +3 -3
- package/comandos/swl/discutir-fase.md +20 -2
- package/comandos/swl/ejecutar-fase.md +53 -6
- package/comandos/swl/evolucionar.md +1 -1
- package/comandos/swl/inbox.md +1 -1
- package/comandos/swl/instalar.md +1 -1
- package/comandos/swl/nemesis.md +1 -1
- package/comandos/swl/planear-fase.md +17 -1
- package/comandos/swl/plugins.md +1 -1
- package/comandos/swl/release.md +1 -1
- package/comandos/swl/status.md +279 -0
- package/comandos/swl/verificar.md +26 -1
- package/habilidades/ai-runtime-security/SKILL.md +1 -1
- package/habilidades/auto-evolucion-protocolo/SKILL.md +276 -276
- package/habilidades/benchmark-memoria/SKILL.md +1 -1
- package/habilidades/calidad-contract-testing/SKILL.md +165 -0
- package/habilidades/changelog-generator/SKILL.md +9 -2
- package/habilidades/changelog-generator/scripts/parse-commits.js +11 -1
- package/habilidades/diagrama-arquitectura/SKILL.md +1 -1
- package/habilidades/drift-detection/SKILL.md +179 -179
- package/habilidades/ejecutar-fase/SKILL.md +64 -14
- package/habilidades/estructura-proyecto-claude/SKILL.md +17 -14
- package/habilidades/estructura-proyecto-claude/recursos/configuracion-y-extensiones.md +34 -23
- package/habilidades/estructura-proyecto-claude/recursos/frontmatter-y-hooks-referencia.md +70 -53
- package/habilidades/estructura-proyecto-claude/recursos/mcp-json-template.json +57 -77
- package/habilidades/extractor-de-aprendizajes/SKILL.md +9 -5
- package/habilidades/harness-claude-code/SKILL.md +10 -7
- package/{reglas/harness-claude-code.md → habilidades/harness-claude-code/recursos/disciplina-harness-regla.md} +2 -2
- package/habilidades/instalar-sistema/SKILL.md +3 -3
- package/habilidades/meta-skills-estandar/recursos/frameworks-seguridad.md +1 -1
- package/habilidades/perfil-usuario/SKILL.md +200 -200
- package/habilidades/planear-fase/SKILL.md +25 -4
- package/habilidades/proceso-ddia-fundamentos/SKILL.md +1 -1
- package/habilidades/proceso-ddia-streaming/SKILL.md +4 -4
- package/habilidades/proceso-debate-adversarial/SKILL.md +2 -2
- package/habilidades/protocolo-revision-swl/SKILL.md +1 -1
- package/habilidades/seguridad-skills-ia/SKILL.md +1 -1
- package/habilidades/swl-claudemd/SKILL.md +50 -210
- package/habilidades/swl-claudemd/recursos/contrato-aprender.md +83 -0
- package/habilidades/swl-claudemd/recursos/duplicacion-reglas-globales.md +85 -0
- package/habilidades/swl-claudemd/recursos/plantillas-init.md +94 -0
- package/habilidades/swl-dashboard/SKILL.md +9 -9
- package/habilidades/swl-revisar-impacto/SKILL.md +1 -1
- package/habilidades/tdd-workflow/SKILL.md +45 -5
- package/habilidades/validacion-ci-sistema/SKILL.md +3 -3
- package/hooks/calidad-pre-commit.js +340 -3
- package/hooks/ciclo-evolucion-subagente.js +26 -0
- package/hooks/ciclo-evolucion.js +26 -0
- package/hooks/extraccion-aprendizajes.js +13 -0
- package/hooks/lib/ciclo-evolucion.js +47 -0
- package/hooks/{auto-evolucion.js → lib/etapa-auto-evolucion.js} +701 -700
- package/hooks/{metricas-evolucion.js → lib/etapa-metricas.js} +388 -376
- package/hooks/{actualizar-perfil-usuario.js → lib/etapa-perfil-usuario.js} +376 -364
- package/hooks/lib/evolution-tracker.js +24 -3
- package/hooks/spec-gate.js +211 -0
- package/hooks/tdd-gate.js +241 -0
- package/hooks/validar-intent-spec.js +30 -10
- package/llms.txt +6 -6
- package/manifiestos/hooks-config.json +26 -17
- package/manifiestos/modulos.json +17 -14
- package/manifiestos/skills-lock.json +63 -56
- package/package.json +2 -2
- package/plugin.json +6 -10
- package/reglas/accesibilidad.md +10 -0
- package/reglas/api-diseno.md +9 -0
- package/reglas/auditorias-documentales-estructurales.md +7 -0
- package/reglas/cloud-infra.md +8 -0
- package/reglas/fragmentos-compartidos.md +5 -0
- package/reglas/gobernanza.md +4 -4
- package/reglas/hooks.md +6 -0
- package/reglas/intent-engineering.md +4 -0
- package/reglas/markitdown.md +8 -0
- package/reglas/memoria-consolidada.md +1 -1
- package/reglas/patrones.md +6 -0
- package/reglas/registro-componentes-nuevos.md +10 -1
- package/reglas/seguridad-agentes.md +1 -1
- package/reglas/skills-estandar.md +6 -0
- package/reglas/testing.md +7 -0
- package/reglas/tests-cleanup.md +4 -0
- package/reglas/usar-sistema-swl.md +1 -1
- package/scripts/lib/gitignore-manifest.js +29 -1
- package/scripts/lib/plan-lock.js +275 -0
- package/scripts/migrar-fase-dominio.js +0 -1
- package/scripts/verificar-trazabilidad.js +292 -0
- package/agentes/ux-disenador-swl.md +0 -503
- package/comandos/swl/dashboard.md +0 -146
- package/comandos/swl/evolucion-estado.md +0 -191
- package/comandos/swl/metricas.md +0 -376
- package/comandos/swl/salud.md +0 -481
- package/reglas/verificar-citas-temporales.md +0 -139
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: swl:evolucion-estado
|
|
3
|
-
description: Dashboard del ciclo de auto-evolución del sistema SWL. Muestra health_score compuesto, tasa de acción de nudges, densidad de instintos, fallos de agentes, evoluciones aplicadas/revertidas y alertas persistentes. Responde en una pantalla a "¿SWL está aprendiendo esta semana?".
|
|
4
|
-
argument-hint: [--json | --dias=N | --regenerar]
|
|
5
|
-
allowed_tools: ["Read", "Bash"]
|
|
6
|
-
user-invocable: true
|
|
7
|
-
version: "1.0.0"
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
# /swl:evolucion-estado — Dashboard del ciclo de evolución
|
|
11
|
-
|
|
12
|
-
Emite un reporte compacto del estado de auto-evolución del sistema SWL en la
|
|
13
|
-
ventana reciente (default 14 días). Su propósito: responder a la pregunta
|
|
14
|
-
**"¿el sistema está aprendiendo?"** con datos, no impresiones.
|
|
15
|
-
|
|
16
|
-
## Flags
|
|
17
|
-
|
|
18
|
-
- `--json` → emite el JSON crudo de `metricas.json` (útil para pipes).
|
|
19
|
-
- `--dias=N` → regenera métricas con ventana de N días (default 14).
|
|
20
|
-
- `--regenerar` → fuerza recomputo ejecutando el hook `metricas-evolucion.js`.
|
|
21
|
-
Útil cuando no se ha disparado Stop recientemente.
|
|
22
|
-
|
|
23
|
-
## Paso 0 — Asegurar métricas frescas
|
|
24
|
-
|
|
25
|
-
Si se pasó `--regenerar` o `metricas.json` tiene > 24h:
|
|
26
|
-
|
|
27
|
-
```bash
|
|
28
|
-
PATH="/c/Program Files/nodejs:/c/Program Files (x86)/nodejs:$PATH" echo '{}' | node hooks/metricas-evolucion.js
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
## Paso 1 — Cargar métricas
|
|
32
|
-
|
|
33
|
-
```bash
|
|
34
|
-
cat .planning/evolution/metricas.json
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
Si el archivo no existe: ejecutar el regenerado del Paso 0. Si sigue sin
|
|
38
|
-
existir: reportar "el ciclo de evolución no ha corrido aún; ejecuta cualquier
|
|
39
|
-
tarea para poblar métricas iniciales".
|
|
40
|
-
|
|
41
|
-
## Paso 1.5 — Cargar contexto del kernel (gobernanza)
|
|
42
|
-
|
|
43
|
-
Para el bloque **KERNEL** del dashboard, recolectar:
|
|
44
|
-
|
|
45
|
-
```bash
|
|
46
|
-
# 1. Conteo de agentes evolvable=false vs total
|
|
47
|
-
TOTAL=$(ls agentes/*.md | grep -v "^agentes/_" | wc -l)
|
|
48
|
-
EVOL_FALSE=$(grep -l '^evolvable: false' agentes/*.md | wc -l)
|
|
49
|
-
|
|
50
|
-
# 2. Último ADR del repo madre — el más reciente por fecha en frontmatter
|
|
51
|
-
ULTIMO_ADR=$(ls .planning/adrs/[0-9]*.md | sort -r | head -1)
|
|
52
|
-
TITULO=$(head -1 "$ULTIMO_ADR" | sed 's/^# //')
|
|
53
|
-
FECHA=$(grep -m1 '^\*\*Fecha\*\*:' "$ULTIMO_ADR" | sed 's/.*\*\*Fecha\*\*:\s*//')
|
|
54
|
-
|
|
55
|
-
echo "ADR_KERNEL_LINEA=\"$TITULO — $FECHA\""
|
|
56
|
-
echo "RATIO=\"$EVOL_FALSE/$TOTAL\""
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
Estos valores alimentan la sección KERNEL del template.
|
|
60
|
-
|
|
61
|
-
Si `.planning/evolution/politica-evolvable.md` no existe, reportar como
|
|
62
|
-
hallazgo crítico: el kernel SIN política documentada es violación de
|
|
63
|
-
`reglas/gobernanza.md`.
|
|
64
|
-
|
|
65
|
-
## Paso 2 — Emitir el dashboard (formato humano)
|
|
66
|
-
|
|
67
|
-
Template de salida:
|
|
68
|
-
|
|
69
|
-
```
|
|
70
|
-
═══════════════════════════════════════════════════════════════
|
|
71
|
-
SWL — Estado del ciclo de evolución
|
|
72
|
-
Ventana: últimos N días · Generado: <ts>
|
|
73
|
-
═══════════════════════════════════════════════════════════════
|
|
74
|
-
|
|
75
|
-
Health score: <N>/100 <badge>
|
|
76
|
-
|
|
77
|
-
NUDGES
|
|
78
|
-
Emitidos .............. <total>
|
|
79
|
-
Accionados ............ <n> (<tasa>%)
|
|
80
|
-
Pendientes ............ <n>
|
|
81
|
-
Por tipo:
|
|
82
|
-
perfil-usuario <a>/<t> (<%>)
|
|
83
|
-
auto-evolucion <a>/<t> (<%>)
|
|
84
|
-
consolidacion <a>/<t> (<%>)
|
|
85
|
-
|
|
86
|
-
INSTINTOS
|
|
87
|
-
Proyecto .............. <n>
|
|
88
|
-
Global ................ <n>
|
|
89
|
-
Perfil-usuario ........ <n>
|
|
90
|
-
Aprendizajes totales .. <n>
|
|
91
|
-
|
|
92
|
-
AGENTES (14d)
|
|
93
|
-
Runs totales .......... <n>
|
|
94
|
-
Fallos ................ <n>
|
|
95
|
-
Tasa de éxito ......... <%>
|
|
96
|
-
|
|
97
|
-
EVOLUCIONES (30d)
|
|
98
|
-
Aplicadas ............. <n>
|
|
99
|
-
Revertidas ............ <n>
|
|
100
|
-
Neta .................. <n>
|
|
101
|
-
Rollback ratio ........ <%> (N/A si aplicadas == 0)
|
|
102
|
-
|
|
103
|
-
CALIDAD CONDUCTUAL (14d)
|
|
104
|
-
Fallos por tipo:
|
|
105
|
-
bad_output_format <n>
|
|
106
|
-
tool_error <n>
|
|
107
|
-
timeout <n>
|
|
108
|
-
schema_violation <n>
|
|
109
|
-
task_incomplete <n>
|
|
110
|
-
unknown <n>
|
|
111
|
-
Reintentos consecutivos
|
|
112
|
-
Total ............... <n> (mismo agente, misma task, ≤30 min)
|
|
113
|
-
Top agente .......... <agente>: <n>
|
|
114
|
-
Latencia top agente
|
|
115
|
-
Mediana ............. <ms>
|
|
116
|
-
p95 ................. <ms>
|
|
117
|
-
Sin instrumentación todavía:
|
|
118
|
-
• precision_routing_fase_dominio
|
|
119
|
-
• utilidad_memoria_recuperada
|
|
120
|
-
• violaciones_formato_post_ejecucion
|
|
121
|
-
|
|
122
|
-
ALERTAS PERSISTENTES
|
|
123
|
-
<si alertasActivas.length === 0>
|
|
124
|
-
Sin alertas.
|
|
125
|
-
<sino>
|
|
126
|
-
[!] kind=X target=Y count=Z (primera: fecha)
|
|
127
|
-
...
|
|
128
|
-
|
|
129
|
-
KERNEL (gobernanza)
|
|
130
|
-
Política evolvable .... .planning/evolution/politica-evolvable.md
|
|
131
|
-
Último ADR kernel ..... <ADR-NNNN — título — fecha>
|
|
132
|
-
Agentes evolvable=false <n>/<total>
|
|
133
|
-
|
|
134
|
-
═══════════════════════════════════════════════════════════════
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
## Paso 3 — Calcular badge del health_score
|
|
138
|
-
|
|
139
|
-
| Rango | Badge | Interpretación |
|
|
140
|
-
|-------|-------|----------------|
|
|
141
|
-
| ≥ 90 | 🏆 Óptimo | ciclo completo, cerrado y saludable |
|
|
142
|
-
| ≥ 75 | 🥇 Saludable | funcionando con pequeñas mejoras pendientes |
|
|
143
|
-
| ≥ 60 | 🥈 Parcial | hay piezas sin activar; revisar recomendaciones |
|
|
144
|
-
| ≥ 40 | 🥉 Esqueleto | infraestructura existe pero poco uso real |
|
|
145
|
-
| < 40 | ⚠️ Dormido | el ciclo no está corriendo |
|
|
146
|
-
|
|
147
|
-
## Paso 4 — Recomendaciones contextuales
|
|
148
|
-
|
|
149
|
-
Al final del dashboard, sugerir acciones según las métricas:
|
|
150
|
-
|
|
151
|
-
- Si `instintos.proyecto === 0` y `aprendizajes_totales > 10`:
|
|
152
|
-
→ `npx -y @saulwade/swl-ses@latest bootstrap-instincts` (pobla desde APRENDIZAJES.md)
|
|
153
|
-
|
|
154
|
-
- Si `nudges.tasaAccion < 0.3` y `nudges.total > 5`:
|
|
155
|
-
→ "Muchos nudges ignorados. Revisa `.planning/evolution/alertas-persistentes.json`"
|
|
156
|
-
|
|
157
|
-
- Si `alertasActivas.length > 0`:
|
|
158
|
-
→ listar cada alerta con `/swl:evolucionar <target>` o cmd correspondiente
|
|
159
|
-
|
|
160
|
-
- Si `agentes.tasaExito < 70` y `totalRuns > 5`:
|
|
161
|
-
→ "Agentes con tasa de éxito baja. Candidatos a `/swl:evolucionar`:
|
|
162
|
-
<top 3 de porAgente con más fallos>"
|
|
163
|
-
|
|
164
|
-
- Si `evoluciones.revertidas > evoluciones.aplicadas / 2`:
|
|
165
|
-
→ "Muchas evoluciones revertidas — revisar si el gate de regresión
|
|
166
|
-
está siendo demasiado laxo o si los evals son inconsistentes"
|
|
167
|
-
|
|
168
|
-
- Si `health_score >= 90`:
|
|
169
|
-
→ "Sistema en óptimo. Posible candidato a habilitar modo autónomo
|
|
170
|
-
de `auto-evolucion-swl`. Ver `agentes/auto-evolucion-swl.md` —
|
|
171
|
-
sección 'Autonomía condicional'"
|
|
172
|
-
|
|
173
|
-
- Si `health_score < 95`:
|
|
174
|
-
→ "Para subir el score, consultar `.planning/ROADMAP-EVOLUCION.md` —
|
|
175
|
-
documenta los 5 hitos por fase y cuánto aporta cada uno. Sin uso
|
|
176
|
-
operacional real (nudges accionados, runs reales, evoluciones), el
|
|
177
|
-
score no sube por infraestructura sola."
|
|
178
|
-
|
|
179
|
-
## Anti-substitution guardrails
|
|
180
|
-
|
|
181
|
-
- Archivo de métricas: **siempre** `.planning/evolution/metricas.json` (nunca `.planning/metricas.json`, `evolucion.json`, `estado-evolucion.json`).
|
|
182
|
-
- Hook que regenera: **siempre** `hooks/metricas-evolucion.js` (nunca `metrics.js`, `evolucion-metricas.js`, `evolution-metrics.js`).
|
|
183
|
-
- Para forzar regen: pipe `echo '{}' | node ...`, nunca invocar `require()` directo.
|
|
184
|
-
|
|
185
|
-
## Response Discipline
|
|
186
|
-
|
|
187
|
-
Si el usuario pasa `--json`: respuesta = **contenido crudo del archivo**,
|
|
188
|
-
sin prosa ni comentarios.
|
|
189
|
-
|
|
190
|
-
Si no: dashboard formateado con las 5 secciones. Las recomendaciones del
|
|
191
|
-
Paso 4 van al final, máximo 3 items priorizados. Sin repetir datos del dashboard.
|
package/comandos/swl/metricas.md
DELETED
|
@@ -1,376 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: swl:metricas
|
|
3
|
-
description: Muestra métricas acumuladas de la sesión de trabajo actual: tokens consumidos, costo estimado en USD, tool calls y distribución por herramienta. Cargar cuando el usuario quiera ver el consumo de la sesión, verificar el presupuesto o entender qué herramientas dominan el costo.
|
|
4
|
-
allowed_tools: ["Read", "Write", "Bash", "Glob", "Grep"]
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# /swl:metricas — Métricas de la sesión actual
|
|
8
|
-
|
|
9
|
-
Muestra las métricas acumuladas de la sesión de trabajo actual: tokens,
|
|
10
|
-
costo estimado, herramientas más usadas y estado del presupuesto configurado.
|
|
11
|
-
|
|
12
|
-
## Cuándo usar
|
|
13
|
-
|
|
14
|
-
- Para saber cuánto se ha consumido en la sesión antes de continuar
|
|
15
|
-
- Para identificar qué operaciones generan más costo
|
|
16
|
-
- Para verificar si se está cerca del límite de presupuesto
|
|
17
|
-
- Al final de una sesión para registrar el consumo real
|
|
18
|
-
|
|
19
|
-
## Subcomandos
|
|
20
|
-
|
|
21
|
-
```
|
|
22
|
-
/swl:metricas — Resumen de métricas de la sesión
|
|
23
|
-
/swl:metricas detalle — Desglose completo por herramienta y timeline
|
|
24
|
-
/swl:metricas fases — Progreso de fases del proyecto desde feature-list.json
|
|
25
|
-
/swl:metricas loops — Trayectorias de loops iterativos desde .planning/loops/
|
|
26
|
-
/swl:metricas historico — Abre el dashboard histórico multi-sesión (alias de /swl:dashboard)
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
---
|
|
30
|
-
|
|
31
|
-
## Paso 1 — Leer fuentes de datos disponibles
|
|
32
|
-
|
|
33
|
-
### Fuente 1: archivo de métricas de sesión
|
|
34
|
-
|
|
35
|
-
```bash
|
|
36
|
-
# Bridge de tracking generado por el hook de costos
|
|
37
|
-
ls /tmp/swl-costs-*.json 2>/dev/null | sort -t- -k3 -n | tail -1
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
Si existe, leerlo. Contiene el acumulado de tool calls, tokens y costos de la sesión.
|
|
41
|
-
|
|
42
|
-
### Fuente 2: métricas persistidas del proyecto
|
|
43
|
-
|
|
44
|
-
```bash
|
|
45
|
-
cat .planning/METRICAS.md 2>/dev/null || echo "(sin métricas previas guardadas)"
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
### Fuente 3: configuración de presupuesto
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
cat manifiestos/hooks-config.json | python3 -c "
|
|
52
|
-
import json, sys
|
|
53
|
-
cfg = json.load(sys.stdin)
|
|
54
|
-
budget = cfg.get('costBudget', {})
|
|
55
|
-
print('maxUsd:', budget.get('maxUsd', 'no configurado'))
|
|
56
|
-
print('maxTokens:', budget.get('maxTokens', 'no configurado'))
|
|
57
|
-
print('alertAt:', budget.get('alertAt', 'no configurado'))
|
|
58
|
-
" 2>/dev/null || echo "(sin presupuesto configurado)"
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
---
|
|
62
|
-
|
|
63
|
-
## Paso 2 — Calcular y mostrar resumen
|
|
64
|
-
|
|
65
|
-
Construir el resumen con los datos disponibles. Si no hay bridge activo,
|
|
66
|
-
usar estimaciones basadas en el historial de `.planning/METRICAS.md`.
|
|
67
|
-
|
|
68
|
-
### Formato de resumen
|
|
69
|
-
|
|
70
|
-
```
|
|
71
|
-
╔══════════════════════════════════════════════════════╗
|
|
72
|
-
║ SWL — Métricas de Sesión ║
|
|
73
|
-
╚══════════════════════════════════════════════════════╝
|
|
74
|
-
|
|
75
|
-
Sesión actual
|
|
76
|
-
─────────────────────────────────────────────────────
|
|
77
|
-
Tool calls totales: NNN
|
|
78
|
-
Tokens consumidos: ~NNN,NNN (entrada + salida)
|
|
79
|
-
Costo estimado: ~$N.NNNN USD
|
|
80
|
-
Modelo predominante: claude-sonnet / claude-opus
|
|
81
|
-
Duración estimada: ~N minutos
|
|
82
|
-
|
|
83
|
-
Presupuesto
|
|
84
|
-
─────────────────────────────────────────────────────
|
|
85
|
-
Límite configurado: $N.NN USD / NNN,NNN tokens
|
|
86
|
-
Consumido: NN% [████████░░] N.NN USD
|
|
87
|
-
Estado: OK / ALERTA / EXCEDIDO
|
|
88
|
-
|
|
89
|
-
Top 5 herramientas por costo
|
|
90
|
-
─────────────────────────────────────────────────────
|
|
91
|
-
1. Bash NNN calls ~$N.NNNN
|
|
92
|
-
2. Read NNN calls ~$N.NNNN
|
|
93
|
-
3. Write NNN calls ~$N.NNNN
|
|
94
|
-
4. Grep NNN calls ~$N.NNNN
|
|
95
|
-
5. Edit NNN calls ~$N.NNNN
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
Si el estado es ALERTA (>= `alertAt` del presupuesto):
|
|
99
|
-
indicar con mensaje visible y sugerir `/swl:compactar` para reducir contexto.
|
|
100
|
-
|
|
101
|
-
Si el estado es EXCEDIDO:
|
|
102
|
-
indicar claramente y recomendar revisar la configuración en `manifiestos/hooks-config.json`.
|
|
103
|
-
|
|
104
|
-
---
|
|
105
|
-
|
|
106
|
-
## Paso 3 (detalle) — Desglose completo
|
|
107
|
-
|
|
108
|
-
Solo si se invocó `/swl:metricas detalle`:
|
|
109
|
-
|
|
110
|
-
### Tabla completa por herramienta
|
|
111
|
-
|
|
112
|
-
```
|
|
113
|
-
Herramienta Calls Tokens entrada Tokens salida Costo USD
|
|
114
|
-
─────────────────────────────────────────────────────────────────────
|
|
115
|
-
Bash NNN NNN,NNN NNN,NNN $N.NNNN
|
|
116
|
-
Read NNN NNN,NNN NNN,NNN $N.NNNN
|
|
117
|
-
Write NNN NNN,NNN NNN,NNN $N.NNNN
|
|
118
|
-
Edit NNN NNN,NNN NNN,NNN $N.NNNN
|
|
119
|
-
Grep NNN NNN,NNN NNN,NNN $N.NNNN
|
|
120
|
-
Glob NNN NNN,NNN NNN,NNN $N.NNNN
|
|
121
|
-
Agent NNN NNN,NNN NNN,NNN $N.NNNN
|
|
122
|
-
Skill NNN NNN,NNN NNN,NNN $N.NNNN
|
|
123
|
-
─────────────────────────────────────────────────────────────────────
|
|
124
|
-
TOTAL NNN NNN,NNN NNN,NNN $N.NNNN
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
### Comparativa histórica (si existe usage.db)
|
|
128
|
-
|
|
129
|
-
Ejecutar el siguiente script Python para comparar la sesión actual contra el promedio
|
|
130
|
-
histórico de los últimos 30 días almacenado en `~/.claude/usage.db`:
|
|
131
|
-
|
|
132
|
-
```bash
|
|
133
|
-
python3 - << 'EOF'
|
|
134
|
-
import sqlite3, json, os
|
|
135
|
-
from pathlib import Path
|
|
136
|
-
from datetime import datetime, timedelta, timezone
|
|
137
|
-
|
|
138
|
-
db = Path.home() / ".claude" / "usage.db"
|
|
139
|
-
if not db.exists():
|
|
140
|
-
print("(sin base de datos histórica — ejecuta /swl:dashboard primero para generarla)")
|
|
141
|
-
else:
|
|
142
|
-
conn = sqlite3.connect(db)
|
|
143
|
-
conn.row_factory = sqlite3.Row
|
|
144
|
-
ahora = datetime.now(timezone.utc)
|
|
145
|
-
hace30 = (ahora - timedelta(days=30)).isoformat()
|
|
146
|
-
hoy = ahora.strftime("%Y-%m-%d")
|
|
147
|
-
|
|
148
|
-
# Promedio de los últimos 30 días por sesión
|
|
149
|
-
res = conn.execute("""
|
|
150
|
-
SELECT COUNT(DISTINCT session_id) as sesiones,
|
|
151
|
-
ROUND(AVG(input_tokens + output_tokens), 0) as avg_tokens_por_turno,
|
|
152
|
-
SUM(input_tokens + output_tokens) as total_tokens
|
|
153
|
-
FROM turns WHERE timestamp >= ?
|
|
154
|
-
""", (hace30,)).fetchone()
|
|
155
|
-
|
|
156
|
-
# Top 5 agentes SWL históricos
|
|
157
|
-
try:
|
|
158
|
-
agentes = conn.execute("""
|
|
159
|
-
SELECT agent_name, COUNT(*) as n
|
|
160
|
-
FROM turns
|
|
161
|
-
WHERE agent_name IS NOT NULL AND timestamp >= ?
|
|
162
|
-
GROUP BY agent_name ORDER BY n DESC LIMIT 5
|
|
163
|
-
""", (hace30,)).fetchall()
|
|
164
|
-
top_agentes = ", ".join(f"{r['agent_name']}({r['n']})" for r in agentes) or "(sin datos)"
|
|
165
|
-
except Exception:
|
|
166
|
-
top_agentes = "(columna agent_name no disponible — requiere nuevo scan)"
|
|
167
|
-
|
|
168
|
-
# Top 5 skills SWL históricos
|
|
169
|
-
try:
|
|
170
|
-
skills = conn.execute("""
|
|
171
|
-
SELECT skill_name, COUNT(*) as n
|
|
172
|
-
FROM turns
|
|
173
|
-
WHERE skill_name IS NOT NULL AND timestamp >= ?
|
|
174
|
-
GROUP BY skill_name ORDER BY n DESC LIMIT 5
|
|
175
|
-
""", (hace30,)).fetchall()
|
|
176
|
-
top_skills = ", ".join(f"{r['skill_name']}({r['n']})" for r in skills) or "(sin datos)"
|
|
177
|
-
except Exception:
|
|
178
|
-
top_skills = "(columna skill_name no disponible — requiere nuevo scan)"
|
|
179
|
-
|
|
180
|
-
conn.close()
|
|
181
|
-
print(f"\nComparativa histórica (últimos 30 días)")
|
|
182
|
-
print(f"{'─'*52}")
|
|
183
|
-
print(f" Sesiones registradas: {res['sesiones'] or 0}")
|
|
184
|
-
print(f" Total tokens: {(res['total_tokens'] or 0):,}")
|
|
185
|
-
print(f" Avg tokens/turno: {int(res['avg_tokens_por_turno'] or 0):,}")
|
|
186
|
-
print(f" Top agentes SWL: {top_agentes}")
|
|
187
|
-
print(f" Top skills SWL: {top_skills}")
|
|
188
|
-
print(f"\n Para ver gráficas completas: /swl:dashboard")
|
|
189
|
-
EOF
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
### Desglose por agente SWL (sesión actual)
|
|
193
|
-
|
|
194
|
-
Leer el bridge `/tmp/swl-costs-*.json` activo y extraer `costePorAgente`:
|
|
195
|
-
|
|
196
|
-
```bash
|
|
197
|
-
python3 - << 'EOF'
|
|
198
|
-
import json, glob, os
|
|
199
|
-
bridges = sorted(glob.glob(os.path.join(os.environ.get('TMPDIR', '/tmp'), 'swl-costs-*.json')))
|
|
200
|
-
if not bridges:
|
|
201
|
-
print("(sin datos de agentes en esta sesión)")
|
|
202
|
-
else:
|
|
203
|
-
data = json.load(open(bridges[-1]))
|
|
204
|
-
agentes = data.get('costePorAgente', {})
|
|
205
|
-
if not agentes:
|
|
206
|
-
print("(no se invocaron agentes SWL en esta sesión)")
|
|
207
|
-
else:
|
|
208
|
-
total_costo = data.get('costoTotal', 0)
|
|
209
|
-
print(f"\nAgentes SWL — sesión actual")
|
|
210
|
-
print("─" * 68)
|
|
211
|
-
print(f" {'Agente':<35} {'Calls':>6} {'Tokens':>9} {'Costo':>8} {'%':>5}")
|
|
212
|
-
print("─" * 68)
|
|
213
|
-
for nombre, d in sorted(agentes.items(), key=lambda x: -x[1].get('costo', 0)):
|
|
214
|
-
pct = f"{d['costo']/total_costo*100:.1f}%" if total_costo > 0 else "—"
|
|
215
|
-
nombre_c = nombre[:35]
|
|
216
|
-
print(f" {nombre_c:<35} {d.get('llamadas',0):>6} {d.get('tokens',0):>9,} ${d.get('costo',0):>7.4f} {pct:>5}")
|
|
217
|
-
print("─" * 68)
|
|
218
|
-
EOF
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
### Timeline de actividad
|
|
222
|
-
|
|
223
|
-
Agrupar las tool calls por bloque de tiempo (5 minutos) y mostrar la distribución
|
|
224
|
-
de actividad a lo largo de la sesión. Útil para identificar picos de consumo
|
|
225
|
-
asociados a tareas específicas.
|
|
226
|
-
|
|
227
|
-
---
|
|
228
|
-
|
|
229
|
-
## Paso 4 — Persistir en METRICAS.md (opcional)
|
|
230
|
-
|
|
231
|
-
Si el usuario lo solicita o si se detecta fin de sesión (via checkpoint):
|
|
232
|
-
|
|
233
|
-
```bash
|
|
234
|
-
cat >> .planning/METRICAS.md << 'EOF'
|
|
235
|
-
|
|
236
|
-
## Sesión YYYY-MM-DD HH:MM
|
|
237
|
-
|
|
238
|
-
- Tool calls: NNN
|
|
239
|
-
- Tokens: ~NNN,NNN
|
|
240
|
-
- Costo estimado: ~$N.NNNN USD
|
|
241
|
-
- Modelo: claude-sonnet
|
|
242
|
-
- Duración: ~N min
|
|
243
|
-
- Comando que más consumió: Bash (NN%)
|
|
244
|
-
EOF
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
---
|
|
248
|
-
|
|
249
|
-
---
|
|
250
|
-
|
|
251
|
-
## Subcomando: `fases` — Progreso de fases del proyecto
|
|
252
|
-
|
|
253
|
-
Si el usuario invoca `/swl:metricas fases`, muestra el estado actual de las
|
|
254
|
-
fases del proyecto leyendo el JSON derivado de `HOJA-RUTA.md`.
|
|
255
|
-
|
|
256
|
-
### Generación y lectura del estado
|
|
257
|
-
|
|
258
|
-
```bash
|
|
259
|
-
# Regenerar el JSON desde HOJA-RUTA.md (fuente de verdad markdown)
|
|
260
|
-
node scripts/derivar-feature-list.js
|
|
261
|
-
|
|
262
|
-
# Leer el JSON generado en .planning/feature-list.json
|
|
263
|
-
cat .planning/feature-list.json | python3 -c "
|
|
264
|
-
import json, sys
|
|
265
|
-
data = json.load(sys.stdin)
|
|
266
|
-
t = data['totales']
|
|
267
|
-
total = t['fases'] or 1
|
|
268
|
-
pct = (t['completadas'] / total) * 100
|
|
269
|
-
|
|
270
|
-
print(f\"\\nSWL — Progreso de fases del proyecto\")
|
|
271
|
-
print('─' * 60)
|
|
272
|
-
print(f\" Total de fases: {t['fases']}\")
|
|
273
|
-
print(f\" Completadas: {t['completadas']} ({pct:.0f}%)\")
|
|
274
|
-
print(f\" En progreso: {t['en_progreso']}\")
|
|
275
|
-
print(f\" Pendientes: {t['pendientes']}\")
|
|
276
|
-
print(f\" Bloqueadas: {t['bloqueadas']}\")
|
|
277
|
-
print(f\" Spec lista: {t['spec_listas']}\")
|
|
278
|
-
print('─' * 60)
|
|
279
|
-
print()
|
|
280
|
-
for f in data['fases']:
|
|
281
|
-
estado = f['estado']
|
|
282
|
-
marca = {'completado': '✓', 'en_progreso': '◐', 'pendiente': '○',
|
|
283
|
-
'bloqueado': '✗', 'spec_listo': '◔'}.get(estado, '?')
|
|
284
|
-
nombre = f['nombre'][:48]
|
|
285
|
-
art = f.get('artefactos') or {}
|
|
286
|
-
plan = ' [PLAN]' if art.get('plan_md') else ''
|
|
287
|
-
resumen = ' [RESUMEN]' if art.get('resumen_md') else ''
|
|
288
|
-
print(f\" {marca} Fase {f['numero']:>2}: {nombre:<50}{plan}{resumen}\")
|
|
289
|
-
print()
|
|
290
|
-
print(f\" Fuente: {data['fuente']} · Generado: {data['generado_en']}\")
|
|
291
|
-
"
|
|
292
|
-
```
|
|
293
|
-
|
|
294
|
-
### Lo que se reporta
|
|
295
|
-
|
|
296
|
-
- **Totales**: cuántas fases hay y cuántas en cada estado canónico (`completado`,
|
|
297
|
-
`en_progreso`, `pendiente`, `bloqueado`, `spec_listo`).
|
|
298
|
-
- **Lista de fases** con marca visual de estado y artefactos presentes
|
|
299
|
-
(`[PLAN]` si existe `0N-PLAN.md`, `[RESUMEN]` si existe `0N-RESUMEN.md`).
|
|
300
|
-
- **Timestamp** de generación para detectar staleness.
|
|
301
|
-
|
|
302
|
-
### Cuándo usar
|
|
303
|
-
|
|
304
|
-
- Antes de retomar trabajo en una fase, para ver el estado actualizado.
|
|
305
|
-
- Al cerrar una sesión productiva, para verificar progreso vs HOJA-RUTA.md.
|
|
306
|
-
- Para auditoría programática (consumir el JSON desde un hook o dashboard externo).
|
|
307
|
-
|
|
308
|
-
### Detección de drift
|
|
309
|
-
|
|
310
|
-
Si `HOJA-RUTA.md` se modifica pero `feature-list.json` no se regenera, los datos
|
|
311
|
-
quedan desactualizados. Para verificar:
|
|
312
|
-
|
|
313
|
-
```bash
|
|
314
|
-
node scripts/derivar-feature-list.js --check
|
|
315
|
-
# exit 0 = sincronizado, exit 2 = drift detectado
|
|
316
|
-
```
|
|
317
|
-
|
|
318
|
-
`/swl:metricas fases` siempre regenera primero, así que ve estado fresco.
|
|
319
|
-
|
|
320
|
-
---
|
|
321
|
-
|
|
322
|
-
## Subcomando: `loops` — Trayectorias de loops iterativos
|
|
323
|
-
|
|
324
|
-
Si el usuario invoca `/swl:metricas loops`, leer las corridas registradas por
|
|
325
|
-
`hooks/lib/loop-telemetry.js` en `.planning/loops/`:
|
|
326
|
-
|
|
327
|
-
```bash
|
|
328
|
-
node -e "
|
|
329
|
-
const fs = require('fs'), path = require('path');
|
|
330
|
-
const lt = require('./hooks/lib/loop-telemetry');
|
|
331
|
-
const base = path.join(process.cwd(), lt.DIR_LOOPS);
|
|
332
|
-
let dirs = [];
|
|
333
|
-
try { dirs = fs.readdirSync(base).map(d => path.join(base, d)).filter(d => fs.statSync(d).isDirectory()); } catch {}
|
|
334
|
-
if (dirs.length === 0) { console.log('(sin corridas de loops registradas)'); process.exit(0); }
|
|
335
|
-
for (const dir of dirs.sort().slice(-10)) {
|
|
336
|
-
try {
|
|
337
|
-
const t = lt.analizarTrayectoria(dir);
|
|
338
|
-
const h = lt.leerHandoff(dir);
|
|
339
|
-
console.log(path.basename(dir) + ' | iters: ' + t.totalIteraciones +
|
|
340
|
-
' | keep/revert: ' + t.keeps + '/' + t.reverts +
|
|
341
|
-
' | métrica: ' + t.metricaInicial + ' → ' + t.metricaFinal +
|
|
342
|
-
' | plateau: ' + (t.plateau ? 'SÍ' : 'no') +
|
|
343
|
-
' | status: ' + (h ? h.status : 'en curso'));
|
|
344
|
-
} catch (e) { console.log(path.basename(dir) + ' | (ilegible: ' + e.message + ')'); }
|
|
345
|
-
}
|
|
346
|
-
"
|
|
347
|
-
```
|
|
348
|
-
|
|
349
|
-
Reportar al usuario en tabla: corrida, iteraciones, keep/revert rate, métrica
|
|
350
|
-
inicial → final, plateau y status del handoff. Si alguna corrida activa muestra
|
|
351
|
-
plateau, sugerir cerrarla — seguir iterando sin mejora quema tokens.
|
|
352
|
-
|
|
353
|
-
---
|
|
354
|
-
|
|
355
|
-
## Subcomando: `historico`
|
|
356
|
-
|
|
357
|
-
Si el usuario invoca `/swl:metricas historico`, redirigir inmediatamente a:
|
|
358
|
-
|
|
359
|
-
```
|
|
360
|
-
Invocar Skill("swl-dashboard") con subcomando "dashboard".
|
|
361
|
-
```
|
|
362
|
-
|
|
363
|
-
Muestra el historial completo multi-sesión con gráficas interactivas en
|
|
364
|
-
http://localhost:8080. Ver `/swl:dashboard` para más detalles.
|
|
365
|
-
|
|
366
|
-
---
|
|
367
|
-
|
|
368
|
-
## Notas de precisión
|
|
369
|
-
|
|
370
|
-
Los costos son estimaciones basadas en los precios publicados de la API de Anthropic.
|
|
371
|
-
El costo real puede variar según:
|
|
372
|
-
- Modelo efectivamente usado (fallback a haiku en contextos de bajo riesgo)
|
|
373
|
-
- Caché de prompt (reduce costo de tokens de entrada repetidos)
|
|
374
|
-
- Variaciones de precio por región o plan
|
|
375
|
-
|
|
376
|
-
Para costos exactos, consultar el dashboard de Anthropic Console.
|