@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.
Files changed (108) hide show
  1. package/CLAUDE.md +8 -8
  2. package/README.md +12 -12
  3. package/agentes/accesibilidad-wcag-swl.md +3 -3
  4. package/agentes/auto-evolucion-swl.md +908 -908
  5. package/agentes/disenador-ui-swl.md +6 -5
  6. package/agentes/frontend-angular-swl.md +2 -2
  7. package/agentes/frontend-css-swl.md +2 -2
  8. package/agentes/frontend-react-swl.md +4 -4
  9. package/agentes/frontend-swl.md +6 -6
  10. package/agentes/investigador-ux-swl.md +5 -5
  11. package/agentes/orquestador-swl.md +7 -7
  12. package/agentes/perfilador-usuario-swl.md +308 -308
  13. package/agentes/producto-prd-swl.md +1 -1
  14. package/agentes/red-team-swl.md +218 -218
  15. package/agentes/tdd-qa-swl.md +17 -1
  16. package/comandos/swl/actualizar.md +1 -1
  17. package/comandos/swl/aprender.md +2 -2
  18. package/comandos/swl/aprobar-plan.md +152 -0
  19. package/comandos/swl/ayuda.md +3 -3
  20. package/comandos/swl/discutir-fase.md +20 -2
  21. package/comandos/swl/ejecutar-fase.md +53 -6
  22. package/comandos/swl/evolucionar.md +1 -1
  23. package/comandos/swl/inbox.md +1 -1
  24. package/comandos/swl/instalar.md +1 -1
  25. package/comandos/swl/nemesis.md +1 -1
  26. package/comandos/swl/planear-fase.md +17 -1
  27. package/comandos/swl/plugins.md +1 -1
  28. package/comandos/swl/release.md +1 -1
  29. package/comandos/swl/status.md +279 -0
  30. package/comandos/swl/verificar.md +26 -1
  31. package/habilidades/ai-runtime-security/SKILL.md +1 -1
  32. package/habilidades/auto-evolucion-protocolo/SKILL.md +276 -276
  33. package/habilidades/benchmark-memoria/SKILL.md +1 -1
  34. package/habilidades/calidad-contract-testing/SKILL.md +165 -0
  35. package/habilidades/changelog-generator/SKILL.md +9 -2
  36. package/habilidades/changelog-generator/scripts/parse-commits.js +11 -1
  37. package/habilidades/diagrama-arquitectura/SKILL.md +1 -1
  38. package/habilidades/drift-detection/SKILL.md +179 -179
  39. package/habilidades/ejecutar-fase/SKILL.md +64 -14
  40. package/habilidades/estructura-proyecto-claude/SKILL.md +17 -14
  41. package/habilidades/estructura-proyecto-claude/recursos/configuracion-y-extensiones.md +34 -23
  42. package/habilidades/estructura-proyecto-claude/recursos/frontmatter-y-hooks-referencia.md +70 -53
  43. package/habilidades/estructura-proyecto-claude/recursos/mcp-json-template.json +57 -77
  44. package/habilidades/extractor-de-aprendizajes/SKILL.md +9 -5
  45. package/habilidades/harness-claude-code/SKILL.md +10 -7
  46. package/{reglas/harness-claude-code.md → habilidades/harness-claude-code/recursos/disciplina-harness-regla.md} +2 -2
  47. package/habilidades/instalar-sistema/SKILL.md +3 -3
  48. package/habilidades/meta-skills-estandar/recursos/frameworks-seguridad.md +1 -1
  49. package/habilidades/perfil-usuario/SKILL.md +200 -200
  50. package/habilidades/planear-fase/SKILL.md +25 -4
  51. package/habilidades/proceso-ddia-fundamentos/SKILL.md +1 -1
  52. package/habilidades/proceso-ddia-streaming/SKILL.md +4 -4
  53. package/habilidades/proceso-debate-adversarial/SKILL.md +2 -2
  54. package/habilidades/protocolo-revision-swl/SKILL.md +1 -1
  55. package/habilidades/seguridad-skills-ia/SKILL.md +1 -1
  56. package/habilidades/swl-claudemd/SKILL.md +50 -210
  57. package/habilidades/swl-claudemd/recursos/contrato-aprender.md +83 -0
  58. package/habilidades/swl-claudemd/recursos/duplicacion-reglas-globales.md +85 -0
  59. package/habilidades/swl-claudemd/recursos/plantillas-init.md +94 -0
  60. package/habilidades/swl-dashboard/SKILL.md +9 -9
  61. package/habilidades/swl-revisar-impacto/SKILL.md +1 -1
  62. package/habilidades/tdd-workflow/SKILL.md +45 -5
  63. package/habilidades/validacion-ci-sistema/SKILL.md +3 -3
  64. package/hooks/calidad-pre-commit.js +340 -3
  65. package/hooks/ciclo-evolucion-subagente.js +26 -0
  66. package/hooks/ciclo-evolucion.js +26 -0
  67. package/hooks/extraccion-aprendizajes.js +13 -0
  68. package/hooks/lib/ciclo-evolucion.js +47 -0
  69. package/hooks/{auto-evolucion.js → lib/etapa-auto-evolucion.js} +701 -700
  70. package/hooks/{metricas-evolucion.js → lib/etapa-metricas.js} +388 -376
  71. package/hooks/{actualizar-perfil-usuario.js → lib/etapa-perfil-usuario.js} +376 -364
  72. package/hooks/lib/evolution-tracker.js +24 -3
  73. package/hooks/spec-gate.js +211 -0
  74. package/hooks/tdd-gate.js +241 -0
  75. package/hooks/validar-intent-spec.js +30 -10
  76. package/llms.txt +6 -6
  77. package/manifiestos/hooks-config.json +26 -17
  78. package/manifiestos/modulos.json +17 -14
  79. package/manifiestos/skills-lock.json +63 -56
  80. package/package.json +2 -2
  81. package/plugin.json +6 -10
  82. package/reglas/accesibilidad.md +10 -0
  83. package/reglas/api-diseno.md +9 -0
  84. package/reglas/auditorias-documentales-estructurales.md +7 -0
  85. package/reglas/cloud-infra.md +8 -0
  86. package/reglas/fragmentos-compartidos.md +5 -0
  87. package/reglas/gobernanza.md +4 -4
  88. package/reglas/hooks.md +6 -0
  89. package/reglas/intent-engineering.md +4 -0
  90. package/reglas/markitdown.md +8 -0
  91. package/reglas/memoria-consolidada.md +1 -1
  92. package/reglas/patrones.md +6 -0
  93. package/reglas/registro-componentes-nuevos.md +10 -1
  94. package/reglas/seguridad-agentes.md +1 -1
  95. package/reglas/skills-estandar.md +6 -0
  96. package/reglas/testing.md +7 -0
  97. package/reglas/tests-cleanup.md +4 -0
  98. package/reglas/usar-sistema-swl.md +1 -1
  99. package/scripts/lib/gitignore-manifest.js +29 -1
  100. package/scripts/lib/plan-lock.js +275 -0
  101. package/scripts/migrar-fase-dominio.js +0 -1
  102. package/scripts/verificar-trazabilidad.js +292 -0
  103. package/agentes/ux-disenador-swl.md +0 -503
  104. package/comandos/swl/dashboard.md +0 -146
  105. package/comandos/swl/evolucion-estado.md +0 -191
  106. package/comandos/swl/metricas.md +0 -376
  107. package/comandos/swl/salud.md +0 -481
  108. 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.
@@ -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.