sdd-es 2.0.0 → 2.5.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/settings.json +21 -45
- package/LICENSE +21 -0
- package/README.md +51 -21
- package/agents/architecture-designer.md +174 -0
- package/agents/arquitecto.md +16 -1
- package/agents/asesor-datos.md +15 -1
- package/agents/critico.md +37 -1
- package/agents/desarrollador-backend.md +3 -1
- package/agents/desarrollador-frontend.md +3 -1
- package/agents/disenador-api.md +13 -1
- package/agents/documentador.md +3 -1
- package/agents/investigador.md +3 -1
- package/agents/operaciones.md +3 -1
- package/agents/product-designer.md +232 -0
- package/agents/revisor.md +25 -1
- package/agents/seguridad.md +5 -1
- package/agents/tester.md +3 -1
- package/claude-hooks/agent-memory.js +154 -0
- package/cli/index.js +1 -2
- package/commands/sdd.analizar.md +23 -2
- package/commands/sdd.compliance.md +516 -0
- package/commands/sdd.configurar.md +33 -0
- package/commands/sdd.constitucion.md +198 -23
- package/commands/sdd.construir.md +210 -0
- package/commands/sdd.dise/303/261ar.md +188 -0
- package/commands/sdd.estado.md +68 -1
- package/commands/sdd.exportar.md +344 -0
- package/commands/sdd.implementar.md +203 -23
- package/commands/sdd.interpretar.md +239 -0
- package/commands/sdd.md +70 -1
- package/commands/sdd.optimizar.md +164 -0
- package/commands/sdd.planificar.md +64 -0
- package/commands/sdd.verificar.md +10 -0
- package/craft/accessibility-baseline.md +216 -0
- package/craft/anti-ai-slop.md +158 -0
- package/craft/color.md +160 -0
- package/craft/typography.md +121 -0
- package/design-systems/bold-brutalist/DESIGN.md +239 -0
- package/design-systems/editorial-minimal/DESIGN.md +205 -0
- package/design-systems/neutral-modern/DESIGN.md +227 -0
- package/design-systems/vibrant-consumer/DESIGN.md +257 -0
- package/design-systems/warm-editorial/DESIGN.md +221 -0
- package/docs/AGENTES.md +4 -1
- package/docs/FABRICA.md +164 -115
- package/docs/MEMORIA-Y-OBSERVABILIDAD.md +237 -0
- package/docs/MODELOS.md +3 -0
- package/docs/QUE-PASA-SI-FALLA.md +404 -0
- package/docs/SEGURIDAD-PARA-NOTECNICOS.md +280 -0
- package/package.json +5 -3
- package/skills/cache-audit/SKILL.md +163 -0
- package/skills/critica-diseno/SKILL.md +193 -0
- package/skills/descubrir-idea/SKILL.md +133 -0
- package/skills/effort-router/SKILL.md +128 -0
- package/skills/elegir-direccion/SKILL.md +184 -0
- package/skills/github-connect/IMPLEMENTATION-CHECKLIST.md +297 -0
- package/skills/github-connect/INDEX.md +223 -0
- package/skills/github-connect/INTEGRATION.md +361 -0
- package/skills/github-connect/QUICK-START.md +168 -0
- package/skills/github-connect/README.md +414 -0
- package/skills/github-connect/RESUMEN_IMPLEMENTACION.txt +374 -0
- package/skills/github-connect/SKILL.md +343 -0
- package/skills/github-connect/STRUCTURE.txt +252 -0
- package/skills/github-connect/example-config.yaml +41 -0
- package/skills/github-connect/github-connect.sh +419 -0
- package/skills/interpretar-idea/SKILL.md +254 -0
- package/skills/memory-compactor/SKILL.md +114 -0
- package/skills/modo-guiado/SKILL.md +12 -2
- package/skills/observabilidad-consumo/SKILL.md +164 -0
- package/skills/token-budget/SKILL.md +154 -0
- package/skills/vercel-deploy/00-START-HERE.txt +364 -0
- package/skills/vercel-deploy/CHECKLIST.md +205 -0
- package/skills/vercel-deploy/EXEC-SUMMARY.txt +322 -0
- package/skills/vercel-deploy/FLOW.txt +334 -0
- package/skills/vercel-deploy/INDEX.md +276 -0
- package/skills/vercel-deploy/INTEGRATION.md +328 -0
- package/skills/vercel-deploy/MANIFEST.md +310 -0
- package/skills/vercel-deploy/README.md +65 -0
- package/skills/vercel-deploy/SKILL.md +356 -0
- package/skills/vercel-deploy/deploy.sh +298 -0
- package/skills/vercel-deploy/estado.json.example +205 -0
- package/skills/vercel-deploy/skill.yaml +323 -0
- package/skills/vercel-deploy/vercel-deploy.sh +216 -0
- package/skills/wireframe-mvp/SKILL.md +157 -0
- package/.claude-plugin/marketplace.json +0 -31
- package/.claude-plugin/plugin.json +0 -97
- package/docs/EJEMPLO-PRACTICA.md +0 -383
- package/docs/EJEMPLOS.md +0 -212
- /package/skills/{compresion-tokens.md → compresion-tokens/SKILL.md} +0 -0
- /package/skills/{constitucion-constraint.md → constitucion-constraint/SKILL.md} +0 -0
- /package/skills/{deteccion-stack.md → deteccion-stack/SKILL.md} +0 -0
- /package/skills/{enrutador-agentes.md → enrutador-agentes/SKILL.md} +0 -0
- /package/skills/{gestion-estado.md → gestion-estado/SKILL.md} +0 -0
- /package/skills/{indexador.md → indexador/SKILL.md} +0 -0
- /package/skills/{validacion-spec.md → validacion-spec/SKILL.md} +0 -0
- /package/skills/{verificador-implementacion.md → verificador-implementacion/SKILL.md} +0 -0
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Convierte una idea en texto libre a un IR (Interpreted Requirement) JSON validado. Trabaja en 2 fases - razonamiento libre + extracción JSON. Lee .sdd/descubrimiento.md si existe.
|
|
3
|
+
model: claude-opus-4-8
|
|
4
|
+
allowed-tools: Read, Write
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Skill: Interpretar Idea → IR
|
|
8
|
+
|
|
9
|
+
## Propósito
|
|
10
|
+
|
|
11
|
+
Tomar la idea del usuario (más el contexto de discovery si existe) y convertirla en un **IR JSON válido** que alimente el pipeline FORGE. Sin que el usuario tenga que pensar en estructura, campos, o intención.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Contexto que debes leer primero
|
|
16
|
+
|
|
17
|
+
Antes de empezar, lee:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
cat .sdd/descubrimiento.md 2>/dev/null || echo "SIN_DISCOVERY"
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Si existe `descubrimiento.md`, úsalo como contexto adicional para enriquecer el IR.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Flujo en 2 fases
|
|
28
|
+
|
|
29
|
+
### FASE A — Razonamiento libre (sin JSON)
|
|
30
|
+
|
|
31
|
+
Analiza la idea en prosa libre. **No generes JSON todavía.** Solo piensa:
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
Analizando: "[idea del usuario]"
|
|
35
|
+
Contexto de discovery: [resumen de descubrimiento.md si existe]
|
|
36
|
+
|
|
37
|
+
ANÁLISIS:
|
|
38
|
+
- Tipo de producto: [web app / mobile / api / cli / saas / other]
|
|
39
|
+
- Usuarios principales: [quién lo usa]
|
|
40
|
+
- Problema que resuelve: [qué dolor alivia]
|
|
41
|
+
- Features core (los más críticos para V1): [lista priorizada]
|
|
42
|
+
- Features secundarios (futuro): [lista]
|
|
43
|
+
- Restricciones evidentes: [técnicas, de negocio, de tiempo]
|
|
44
|
+
- Ambigüedades detectadas: [qué no está claro]
|
|
45
|
+
- Asunciones que haré: [cómo resuelvo las ambigüedades]
|
|
46
|
+
- Confianza estimada: [0.0–1.0] por qué
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Sé honesto con la confianza. Una idea vaga tiene confidence 0.5–0.65. Una idea clara tiene 0.8–0.9. Nunca 1.0.
|
|
50
|
+
|
|
51
|
+
### FASE B — Extracción a IR JSON
|
|
52
|
+
|
|
53
|
+
Solo después del análisis, extrae el IR JSON:
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"id": "ir-[slug-del-producto]-001",
|
|
58
|
+
"created_at": "[ISO timestamp]",
|
|
59
|
+
"raw_input": "[idea literal del usuario]",
|
|
60
|
+
"confidence": [0.0–1.0],
|
|
61
|
+
|
|
62
|
+
"product": {
|
|
63
|
+
"name": "[Nombre descriptivo del producto]",
|
|
64
|
+
"type": "[saas|mobile|web|api|cli|other]",
|
|
65
|
+
"tagline": "[Una línea que describe el valor en <10 palabras]",
|
|
66
|
+
"value_proposition": "[Por qué existe este producto, en 1 oración]",
|
|
67
|
+
"target_users": "[Quién lo usa, en lenguaje natural]"
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
"features": {
|
|
71
|
+
"core": [
|
|
72
|
+
"[Feature 1 — lo más esencial del MVP]",
|
|
73
|
+
"[Feature 2]",
|
|
74
|
+
"[Feature 3]",
|
|
75
|
+
"[Feature 4 si aplica]",
|
|
76
|
+
"[Feature 5 si aplica — máximo 5]"
|
|
77
|
+
],
|
|
78
|
+
"nice_to_have": [
|
|
79
|
+
"[Feature futuro 1]",
|
|
80
|
+
"[Feature futuro 2]"
|
|
81
|
+
]
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
"constraints": {
|
|
85
|
+
"budget": "[bajo|medio|alto|ilimitado|null]",
|
|
86
|
+
"timeline": "[ASAP|semanas|meses|flexible|null]",
|
|
87
|
+
"team_size": "[1 persona|equipo pequeño|equipo grande|null]",
|
|
88
|
+
"tech_preference": "[React|Python|Node|null — null si no mencionó]"
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
"assumptions": [
|
|
92
|
+
"[Asunción 1 — lo que decidiste sin que el usuario lo dijera]",
|
|
93
|
+
"[Asunción 2]"
|
|
94
|
+
],
|
|
95
|
+
|
|
96
|
+
"ambiguities": [
|
|
97
|
+
{
|
|
98
|
+
"field": "[campo afectado]",
|
|
99
|
+
"issue": "[qué no estaba claro]",
|
|
100
|
+
"resolution": "[cómo lo resolviste]"
|
|
101
|
+
}
|
|
102
|
+
],
|
|
103
|
+
|
|
104
|
+
"requires_clarification": [true|false],
|
|
105
|
+
"questions_for_user": [
|
|
106
|
+
"[Pregunta 1 si confidence < 0.7 — máximo 1 pregunta]"
|
|
107
|
+
]
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Reglas de validación del IR
|
|
114
|
+
|
|
115
|
+
El IR es válido si:
|
|
116
|
+
|
|
117
|
+
- ✅ `product.type` es uno de: `saas`, `mobile`, `web`, `api`, `cli`, `other`
|
|
118
|
+
- ✅ `features.core` tiene **2–5 items** (no 0, no 6+)
|
|
119
|
+
- ✅ `confidence` está entre `0.0` y `1.0`
|
|
120
|
+
- ✅ `assumptions[]` es un array (puede estar vacío)
|
|
121
|
+
- ✅ `ambiguities[]` es un array (puede estar vacío)
|
|
122
|
+
- ✅ Si `confidence < 0.7` → `requires_clarification: true` y `questions_for_user` tiene **máximo 1 pregunta**
|
|
123
|
+
|
|
124
|
+
Si el IR no cumple alguna regla, corrígelo antes de guardarlo.
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Cuándo preguntar vs. asumir
|
|
129
|
+
|
|
130
|
+
**Asumir siempre** cuando:
|
|
131
|
+
- El usuario no mencionó tecnología → asumir `tech_preference: null`
|
|
132
|
+
- El usuario no mencionó presupuesto → asumir `budget: null`
|
|
133
|
+
- Es obvio por el contexto (ej: "app de citas para peluquería" → `type: web`)
|
|
134
|
+
|
|
135
|
+
**Preguntar solo cuando**:
|
|
136
|
+
- `confidence < 0.7` (la idea es genuinamente ambigua)
|
|
137
|
+
- Y solo **1 pregunta**, la más crítica para desambiguar
|
|
138
|
+
|
|
139
|
+
**Ejemplos de preguntas válidas**:
|
|
140
|
+
- "¿Es para tú negocio personal o para múltiples negocios?"
|
|
141
|
+
- "¿Los usuarios pagan por el servicio o es gratuito?"
|
|
142
|
+
|
|
143
|
+
**Ejemplos de preguntas inválidas** (nunca hacer):
|
|
144
|
+
- "¿Qué tecnología prefieres?" (técnico, no relevante para el IR)
|
|
145
|
+
- "¿Cuántas funcionalidades quieres?" (abierto, sin respuesta útil)
|
|
146
|
+
- "¿Tienes algún prototipo?" (fuera de scope)
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Output final
|
|
151
|
+
|
|
152
|
+
### Si `confidence ≥ 0.7`:
|
|
153
|
+
|
|
154
|
+
1. Muestra el IR en formato legible:
|
|
155
|
+
|
|
156
|
+
```
|
|
157
|
+
═══════════════════════════════════════════
|
|
158
|
+
🎯 TU IDEA INTERPRETADA
|
|
159
|
+
═══════════════════════════════════════════
|
|
160
|
+
|
|
161
|
+
Producto: [product.name]
|
|
162
|
+
Tipo: [product.type en español: "aplicación web" / "app móvil" / etc.]
|
|
163
|
+
Para: [target_users]
|
|
164
|
+
|
|
165
|
+
Qué hace: [value_proposition]
|
|
166
|
+
|
|
167
|
+
Features del MVP:
|
|
168
|
+
✦ [core[0]]
|
|
169
|
+
✦ [core[1]]
|
|
170
|
+
✦ [core[2]]
|
|
171
|
+
[... hasta 5]
|
|
172
|
+
|
|
173
|
+
Para más adelante:
|
|
174
|
+
· [nice_to_have[0] si existe]
|
|
175
|
+
|
|
176
|
+
Confianza: [██████████░░] [confidence*100]%
|
|
177
|
+
|
|
178
|
+
Asunciones que hice:
|
|
179
|
+
→ [assumption[0]]
|
|
180
|
+
→ [assumption[1] si existe]
|
|
181
|
+
|
|
182
|
+
[Si hay ambiguities:]
|
|
183
|
+
Preguntas resueltas:
|
|
184
|
+
✓ [ambiguity[0].issue] → [ambiguity[0].resolution]
|
|
185
|
+
|
|
186
|
+
═══════════════════════════════════════════
|
|
187
|
+
¿Es esto lo que querías?
|
|
188
|
+
Escribe "sí" para continuar al diseño
|
|
189
|
+
Escribe "no, cambia [qué]" para corregir
|
|
190
|
+
═══════════════════════════════════════════
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
2. Guarda en `.sdd/ir.json` (solo tras confirmación del usuario)
|
|
194
|
+
3. Guarda el análisis de Fase A en `.sdd/ir-analysis.md`
|
|
195
|
+
|
|
196
|
+
### Si `confidence < 0.7`:
|
|
197
|
+
|
|
198
|
+
1. Muestra la pregunta de clarificación antes de continuar:
|
|
199
|
+
|
|
200
|
+
```
|
|
201
|
+
Antes de continuar, necesito una aclaración:
|
|
202
|
+
|
|
203
|
+
[questions_for_user[0]]
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
2. Espera la respuesta
|
|
207
|
+
3. Incorpora la respuesta al análisis
|
|
208
|
+
4. Re-genera el IR con la nueva información
|
|
209
|
+
5. Ahora confidence debería ser ≥ 0.7 → muestra el IR y pide confirmación
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## Guardar archivos
|
|
214
|
+
|
|
215
|
+
### `.sdd/ir.json`
|
|
216
|
+
El IR JSON completo. Se guarda solo después de que el usuario confirme.
|
|
217
|
+
|
|
218
|
+
### `.sdd/ir-analysis.md`
|
|
219
|
+
El análisis de Fase A. Se guarda siempre (útil para auditoría).
|
|
220
|
+
|
|
221
|
+
```markdown
|
|
222
|
+
# IR Analysis — [product.name]
|
|
223
|
+
|
|
224
|
+
**Fecha**: [timestamp]
|
|
225
|
+
**Idea original**: [raw_input]
|
|
226
|
+
|
|
227
|
+
## Análisis libre (Fase A)
|
|
228
|
+
|
|
229
|
+
[Texto completo del análisis en prosa]
|
|
230
|
+
|
|
231
|
+
## IR generado (Fase B)
|
|
232
|
+
|
|
233
|
+
```json
|
|
234
|
+
[IR JSON completo]
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## Validación
|
|
238
|
+
|
|
239
|
+
- confidence: [valor]
|
|
240
|
+
- requires_clarification: [true/false]
|
|
241
|
+
- errores de validación: [lista o "ninguno"]
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## Casos de prueba esperados
|
|
247
|
+
|
|
248
|
+
| Idea | Confidence esperado | requires_clarification |
|
|
249
|
+
|------|---------------------|----------------------|
|
|
250
|
+
| "App para dentistas que gestionen citas" | 0.82–0.88 | false |
|
|
251
|
+
| "Quiero algo para mis pedidos" | 0.55–0.65 | true |
|
|
252
|
+
| "Plataforma de e-commerce con pagos, inventario y envíos" | 0.80–0.88 | false |
|
|
253
|
+
| "No sé bien, algo para organizar cosas" | 0.40–0.55 | true |
|
|
254
|
+
| "API REST para un sistema de autenticación con JWT y refresh tokens" | 0.88–0.95 | false |
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Comprime los archivos .sdd/memoria/agente-*.md cuando superan 80 entradas o 50KB. Elimina duplicados (misma ruta, fecha distinta — conserva la más reciente) y aplica el diccionario caveman de compresion-tokens (Nivel Full). Produce backup .original antes de comprimir.
|
|
3
|
+
model: claude-haiku-4-5-20251001
|
|
4
|
+
allowed-tools: Read, Write, Bash
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Skill: Memory Compactor
|
|
8
|
+
|
|
9
|
+
## Propósito
|
|
10
|
+
|
|
11
|
+
Los archivos de memoria de agentes crecen indefinidamente a lo largo de proyectos largos. Una memoria de 200 entradas consume ~30KB de ventana de contexto en cada invocación del agente — contexto que podría usarse para la tarea real. Esta skill comprime esos archivos sin perder las decisiones clave.
|
|
12
|
+
|
|
13
|
+
**Cuándo ejecutar:**
|
|
14
|
+
- Cuando el hook `agent-memory.js` emite: `⚠️ Memoria de {agente} supera 50KB`
|
|
15
|
+
- Cuando `/sdd.optimizar memoria` detecta archivos por encima del umbral
|
|
16
|
+
- Manualmente si el agente empieza a ignorar instrucciones (señal de contexto saturado)
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## PASO 1 — Detectar archivos que superan el umbral
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# Listar archivos de memoria con su tamaño
|
|
24
|
+
ls -la .sdd/memoria/agente-*.md 2>/dev/null || echo "SIN_ARCHIVOS_MEMORIA"
|
|
25
|
+
|
|
26
|
+
# Contar entradas por archivo (cada entrada empieza con "## ")
|
|
27
|
+
for f in .sdd/memoria/agente-*.md; do
|
|
28
|
+
[ -f "$f" ] || continue
|
|
29
|
+
entradas=$(grep -c "^## " "$f" 2>/dev/null || echo 0)
|
|
30
|
+
bytes=$(wc -c < "$f" 2>/dev/null || echo 0)
|
|
31
|
+
echo "$f: $entradas entradas, $bytes bytes"
|
|
32
|
+
done
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**Umbral de intervención:** >80 entradas O >50KB. Si ningún archivo supera el umbral, reportar "✅ Memorias dentro del umbral — no se requiere compresión" y terminar.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## PASO 2 — Para cada archivo que supera el umbral
|
|
40
|
+
|
|
41
|
+
### 2a. Crear backup
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
cp .sdd/memoria/agente-{nombre}.md .sdd/memoria/agente-{nombre}.md.original
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### 2b. Leer el archivo completo
|
|
48
|
+
|
|
49
|
+
Parsear línea a línea. Cada entrada tiene este formato:
|
|
50
|
+
```markdown
|
|
51
|
+
## 2026-06-13 — ruta/del/archivo.md
|
|
52
|
+
> resumen de la acción tomada
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### 2c. Eliminar duplicados
|
|
56
|
+
|
|
57
|
+
Agrupar entradas por `archivo` (la parte después del `—` en el encabezado `##`). De cada grupo, conservar **solo la entrada más reciente** (la de fecha más alta). Las fechas están en formato ISO 8601 `YYYY-MM-DD` — ordenar lexicográficamente es suficiente.
|
|
58
|
+
|
|
59
|
+
**Ejemplo:**
|
|
60
|
+
```
|
|
61
|
+
## 2026-06-01 — .sdd/especificaciones/auth/spec.md ← ELIMINAR (más antigua)
|
|
62
|
+
## 2026-06-10 — .sdd/especificaciones/auth/spec.md ← CONSERVAR (más reciente)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### 2d. Aplicar compresión Nivel Full al cuerpo de cada entrada
|
|
66
|
+
|
|
67
|
+
El diccionario completo vive en `{PLUGIN_DIR}/skills/compresion-tokens/SKILL.md`. No duplicar los pares aquí — leer la sección "Diccionario Nivel Full" de esa skill y aplicar los mismos 80+ reemplazos sobre el texto de cada línea `>`.
|
|
68
|
+
|
|
69
|
+
**Patrones que NUNCA comprimir** (igual que en `compresion-tokens`):
|
|
70
|
+
- Rutas de archivo (la parte después del `—` en `##`)
|
|
71
|
+
- Código entre backticks
|
|
72
|
+
- Nombres de variables, funciones, clases
|
|
73
|
+
- URLs y comandos
|
|
74
|
+
|
|
75
|
+
### 2e. Reescribir el archivo comprimido
|
|
76
|
+
|
|
77
|
+
```markdown
|
|
78
|
+
# Memoria del agente: {nombre}
|
|
79
|
+
|
|
80
|
+
[Comprimido por memory-compactor el {fecha}. Backup en .original]
|
|
81
|
+
Léelo al inicio de cada sesión para mantener continuidad entre conversaciones.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
{entradas deduplicadas y comprimidas, ordenadas por fecha descendente}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## PASO 3 — Reporte
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
╔══════════════════════════════════════════════════════════════╗
|
|
94
|
+
║ 🧠 MEMORY COMPACTOR — Resultado ║
|
|
95
|
+
╠══════════════════════════════════════════════════════════════╣
|
|
96
|
+
║ AGENTE | ANTES | DESPUÉS | REDUCCIÓN ║
|
|
97
|
+
║ ─────────────────┼──────────────┼──────────────┼─────────── ║
|
|
98
|
+
║ {nombre} | {N} entr. | {M} entr. | {%}% ║
|
|
99
|
+
║ | {KB_antes}KB | {KB_desp}KB | ║
|
|
100
|
+
╠══════════════════════════════════════════════════════════════╣
|
|
101
|
+
║ Backups guardados en: .sdd/memoria/*.md.original ║
|
|
102
|
+
║ Para restaurar: cp agente-{nombre}.md.original agente-... ║
|
|
103
|
+
╚══════════════════════════════════════════════════════════════╝
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Notas
|
|
109
|
+
|
|
110
|
+
- Esta skill reutiliza el diccionario de `compresion-tokens` — no lo reinventa.
|
|
111
|
+
- La deduplicación es la técnica más efectiva: en proyectos largos, el 40-60% de las entradas son re-escrituras del mismo archivo.
|
|
112
|
+
- Nunca borrar el `.original` automáticamente — el usuario decide cuándo hacerlo.
|
|
113
|
+
- Si un archivo tiene <20 entradas y <20KB, saltar silenciosamente aunque se haya invocado la skill.
|
|
114
|
+
- Esta skill se invoca desde `/sdd.optimizar memoria` y desde `/sdd.comprimir memoria`.
|
|
@@ -20,7 +20,7 @@ grep -q '"perfil": *"guiado"' .sdd/estado.json 2>/dev/null && echo GUIADO
|
|
|
20
20
|
grep -q '^perfil: *guiado' .sdd/sdd.config.yaml 2>/dev/null && echo GUIADO
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
## Reglas de comunicación (las
|
|
23
|
+
## Reglas de comunicación (las 8 reglas)
|
|
24
24
|
|
|
25
25
|
1. **Sin jerga.** Nunca digas "endpoint", "schema", "ORM", "deploy", "lint", "CI". Di "dirección donde vive el dato", "estructura de la información", "guardar en disco", "publicar en internet", "revisión automática de calidad". Si un término técnico es inevitable, defínelo en la misma frase con una analogía.
|
|
26
26
|
|
|
@@ -34,6 +34,15 @@ grep -q '^perfil: *guiado' .sdd/sdd.config.yaml 2>/dev/null && echo GUIADO
|
|
|
34
34
|
|
|
35
35
|
6. **Explica el resultado en términos de lo que el usuario puede hacer ahora.** Al terminar un paso: *"Ya puedes crear tareas y marcarlas como hechas. ¿Quieres que lo publiquemos en internet para usarlo desde el móvil?"* — no *"implementé el CRUD con 14 tests, cobertura 87%"*.
|
|
36
36
|
|
|
37
|
+
7. **Pausar y explicar cuando hay confusión.** Si el usuario dice "no entiendo", "explícame", o "no sé qué significa eso", **pausa inmediatamente** y explica con una analogía del mundo real ANTES de continuar. No hagas jerga. Ejemplo:
|
|
38
|
+
- Usuario: "¿Qué es una base de datos?"
|
|
39
|
+
- Tú (❌ MAL): "Es un SGBD relacional que persiste datos en forma normalizada."
|
|
40
|
+
- Tú (✅ BIEN): "Piensa en una base de datos como una hoja de cálculo (como Excel). Guarda toda la información de tu proyecto — usuarios, productos, mensajes, etc. El sistema la usa para encontrar información rápidamente cuando la necesita."
|
|
41
|
+
|
|
42
|
+
8. **Cierre explícito de cada fase.** Al final de cada FASE (especificar, planificar, implementar, verificar), explica exactamente qué puede hacer el usuario AHORA con lo que se construyó. Ejemplo:
|
|
43
|
+
- ❌ "Implementé el módulo de autenticación con JWT y bcrypt."
|
|
44
|
+
- ✅ "✅ Tu código está listo. Ahora puedes: (1) verlo en GitHub, (2) probarlo en internet, (3) cambiar algo si no te gusta, (4) invitar a otros a trabajar contigo."
|
|
45
|
+
|
|
37
46
|
## Cómo traducir los pasos del flujo
|
|
38
47
|
|
|
39
48
|
| Paso técnico interno | Cómo lo nombras al usuario |
|
|
@@ -72,7 +81,8 @@ Si una verificación falla, NO digas "el test X falló con assertion error". Di:
|
|
|
72
81
|
|
|
73
82
|
## Cierre de cada interacción
|
|
74
83
|
|
|
75
|
-
Termina siempre ofreciendo el siguiente paso como una acción en lenguaje natural, no como un comando:
|
|
84
|
+
Termina siempre ofreciendo el siguiente paso como una acción en lenguaje natural, no como un comando. Usa la Regla 8 para enumerar explícitamente qué puede hacer el usuario ahora:
|
|
76
85
|
|
|
77
86
|
> ✅ Ya está. Tu lista de tareas funciona.
|
|
87
|
+
> Ahora puedes: (1) usarla ahora mismo, (2) invitar a otros a colaborar, (3) cambiar cómo se ve.
|
|
78
88
|
> ¿Quieres que **la publique en internet** para usarla desde cualquier lado? (responde *sí*)
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Lee .sdd/observabilidad/consumo.jsonl y genera un reporte de actividad de agentes — invocaciones por agente, archivos tocados, picos y señales de fan-out excesivo. Referencia cruzada con orquestacion-ptc y compresion-tokens.
|
|
3
|
+
model: claude-haiku-4-5-20251001
|
|
4
|
+
allowed-tools: Read, Bash
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Skill: Observabilidad de Consumo
|
|
8
|
+
|
|
9
|
+
## Propósito
|
|
10
|
+
|
|
11
|
+
Convertir el ledger de consumo en información accionable: ver cuántos agentes se activaron, qué archivos tocaron, en qué momentos hubo picos de actividad y si hay señales de fan-out excesivo que conviene corregir.
|
|
12
|
+
|
|
13
|
+
El ledger es un proxy de magnitud (bytes escritos), no una facturación exacta de tokens — Claude Code no expone el conteo real de tokens al hook. Pero es suficiente para detectar patrones problemáticos.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Lo que lees
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# Ledger completo
|
|
21
|
+
cat .sdd/observabilidad/consumo.jsonl 2>/dev/null || echo "SIN_LEDGER"
|
|
22
|
+
|
|
23
|
+
# Conteo rápido de líneas
|
|
24
|
+
wc -l .sdd/observabilidad/consumo.jsonl 2>/dev/null || echo "0"
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Análisis que produces
|
|
30
|
+
|
|
31
|
+
### 1. Resumen por agente
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
node -e "
|
|
35
|
+
const fs = require('fs');
|
|
36
|
+
const path = '.sdd/observabilidad/consumo.jsonl';
|
|
37
|
+
if (!fs.existsSync(path)) { console.log('Sin datos aún.'); process.exit(0); }
|
|
38
|
+
|
|
39
|
+
const lineas = fs.readFileSync(path, 'utf8').trim().split('\n').filter(Boolean);
|
|
40
|
+
const porAgente = {};
|
|
41
|
+
for (const l of lineas) {
|
|
42
|
+
try {
|
|
43
|
+
const e = JSON.parse(l);
|
|
44
|
+
const a = e.agente || 'main';
|
|
45
|
+
if (!porAgente[a]) porAgente[a] = { invocaciones: 0, bytes: 0, archivos: new Set() };
|
|
46
|
+
porAgente[a].invocaciones++;
|
|
47
|
+
porAgente[a].bytes += e.bytes || 0;
|
|
48
|
+
porAgente[a].archivos.add(e.archivo);
|
|
49
|
+
} catch {}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
console.log('AGENTE | INVOC | BYTES | ARCHIVOS ÚNICOS');
|
|
53
|
+
console.log('-'.repeat(60));
|
|
54
|
+
for (const [a, d] of Object.entries(porAgente).sort((x,y) => y[1].invocaciones - x[1].invocaciones)) {
|
|
55
|
+
console.log(\`\${a.padEnd(19)} | \${String(d.invocaciones).padStart(5)} | \${String(d.bytes).padStart(6)} | \${d.archivos.size}\`);
|
|
56
|
+
}
|
|
57
|
+
console.log('');
|
|
58
|
+
console.log('Total eventos:', lineas.length);
|
|
59
|
+
"
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### 2. Detección de fan-out excesivo
|
|
63
|
+
|
|
64
|
+
Umbrales por defecto (ajustables en `.sdd/sdd.config.yaml`):
|
|
65
|
+
|
|
66
|
+
| Señal | Umbral | Acción sugerida |
|
|
67
|
+
|-------|--------|-----------------|
|
|
68
|
+
| >5 agentes distintos en una fase | Alto | Revisar si la orquestación PTC puede colapsar en menos agentes |
|
|
69
|
+
| >20 invocaciones de un mismo agente | Medio | Revisar si el agente entra en loop o hace trabajo redundante |
|
|
70
|
+
| >500 KB de bytes escritos totales | Informativo | Considerar comprimir memoria con `compresion-tokens` |
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
node -e "
|
|
74
|
+
const fs = require('fs');
|
|
75
|
+
const path = '.sdd/observabilidad/consumo.jsonl';
|
|
76
|
+
if (!fs.existsSync(path)) process.exit(0);
|
|
77
|
+
|
|
78
|
+
const lineas = fs.readFileSync(path, 'utf8').trim().split('\n').filter(Boolean);
|
|
79
|
+
const agentes = new Set();
|
|
80
|
+
const invocPorAgente = {};
|
|
81
|
+
let bytesTotal = 0;
|
|
82
|
+
|
|
83
|
+
for (const l of lineas) {
|
|
84
|
+
try {
|
|
85
|
+
const e = JSON.parse(l);
|
|
86
|
+
const a = e.agente || 'main';
|
|
87
|
+
agentes.add(a);
|
|
88
|
+
invocPorAgente[a] = (invocPorAgente[a] || 0) + 1;
|
|
89
|
+
bytesTotal += e.bytes || 0;
|
|
90
|
+
} catch {}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const alertas = [];
|
|
94
|
+
if (agentes.size > 5) alertas.push('⚠️ Fan-out alto: ' + agentes.size + ' agentes distintos activos');
|
|
95
|
+
for (const [a, n] of Object.entries(invocPorAgente)) {
|
|
96
|
+
if (n > 20) alertas.push('⚠️ Agente en loop posible: ' + a + ' (' + n + ' invocaciones)');
|
|
97
|
+
}
|
|
98
|
+
if (bytesTotal > 500_000) alertas.push('ℹ️ Escritura alta: ' + Math.round(bytesTotal/1024) + ' KB — considera compresion-tokens');
|
|
99
|
+
|
|
100
|
+
if (alertas.length === 0) {
|
|
101
|
+
console.log('✅ Sin alertas de fan-out');
|
|
102
|
+
} else {
|
|
103
|
+
for (const a of alertas) console.log(a);
|
|
104
|
+
}
|
|
105
|
+
"
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### 3. Picos de actividad (top 5 momentos)
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
node -e "
|
|
112
|
+
const fs = require('fs');
|
|
113
|
+
const path = '.sdd/observabilidad/consumo.jsonl';
|
|
114
|
+
if (!fs.existsSync(path)) process.exit(0);
|
|
115
|
+
|
|
116
|
+
const lineas = fs.readFileSync(path, 'utf8').trim().split('\n').filter(Boolean);
|
|
117
|
+
const parsed = lineas.map(l => { try { return JSON.parse(l); } catch { return null; } }).filter(Boolean);
|
|
118
|
+
|
|
119
|
+
// Agrupar por minuto
|
|
120
|
+
const porMinuto = {};
|
|
121
|
+
for (const e of parsed) {
|
|
122
|
+
const minuto = e.ts?.slice(0,16) || 'desconocido';
|
|
123
|
+
porMinuto[minuto] = (porMinuto[minuto] || 0) + 1;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const top = Object.entries(porMinuto).sort((a,b) => b[1] - a[1]).slice(0, 5);
|
|
127
|
+
console.log('TOP 5 MINUTOS DE MAYOR ACTIVIDAD:');
|
|
128
|
+
for (const [m, n] of top) console.log(' ' + m + ' → ' + n + ' eventos');
|
|
129
|
+
"
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## Formato del reporte completo
|
|
135
|
+
|
|
136
|
+
```
|
|
137
|
+
╔══════════════════════════════════════════════════════╗
|
|
138
|
+
║ 📊 CONSUMO DE AGENTES — SDD-ES ║
|
|
139
|
+
╠══════════════════════════════════════════════════════╣
|
|
140
|
+
║ AGENTE | INVOC | BYTES | ARCHIVOS ║
|
|
141
|
+
║ [tabla generada] ║
|
|
142
|
+
╠══════════════════════════════════════════════════════╣
|
|
143
|
+
║ ALERTAS DE FAN-OUT ║
|
|
144
|
+
║ [alertas o "✅ Sin alertas"] ║
|
|
145
|
+
╠══════════════════════════════════════════════════════╣
|
|
146
|
+
║ TOP MOMENTOS DE ACTIVIDAD ║
|
|
147
|
+
║ [top 5 minutos] ║
|
|
148
|
+
╠══════════════════════════════════════════════════════╣
|
|
149
|
+
║ RECOMENDACIONES ║
|
|
150
|
+
║ → Si fan-out alto: revisar skill orquestacion-ptc ║
|
|
151
|
+
║ → Si bytes altos: ejecutar /sdd.comprimir ║
|
|
152
|
+
║ → Si loop agente: revisar el agente con /sdd.estado║
|
|
153
|
+
╚══════════════════════════════════════════════════════╝
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Notas
|
|
159
|
+
|
|
160
|
+
- El ledger se escribe en tiempo real por el hook `agent-memory.js` (PostToolUse)
|
|
161
|
+
- Los `bytes` miden el contenido de cada escritura — son un **proxy de magnitud**, no el consumo real de tokens del modelo
|
|
162
|
+
- Para vaciar el ledger al inicio de una sesión nueva: `echo "" > .sdd/observabilidad/consumo.jsonl`
|
|
163
|
+
- Cruzar con `orquestacion-ptc` para decidir cuándo paralelizar vs. serializar agentes
|
|
164
|
+
- Cruzar con `compresion-tokens` para decidir cuándo comprimir los archivos `.sdd/memoria/`
|