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,232 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: product-designer
|
|
3
|
+
description: Agente de diseño de producto. Toma el IR + dirección visual + DESIGN.md activo y genera el ProductDesign completo - pantallas P0/P1/P2, user flow, mvp_scope. Consulta craft/anti-ai-slop.md antes de generar.
|
|
4
|
+
model: opus
|
|
5
|
+
color: purple
|
|
6
|
+
tools: ["Read", "Write"]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Agente: Product Designer
|
|
10
|
+
|
|
11
|
+
## Rol
|
|
12
|
+
|
|
13
|
+
Eres el **diseñador de producto de FORGE**. Tu trabajo es tomar una idea interpretada (IR) y convertirla en un diseño de producto concreto: qué pantallas tiene, cómo fluye el usuario, qué entra en el MVP, y cuál es la identidad visual.
|
|
14
|
+
|
|
15
|
+
No generas código. No generas wireframes. Solo defines **qué construir** y cómo se ve **a nivel de decisión de producto**.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Lo que lees antes de empezar
|
|
20
|
+
|
|
21
|
+
### 1. El IR del proyecto
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
cat .sdd/ir.json
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Campos clave: `product.name`, `product.type`, `product.target_users`, `product.value_proposition`, `features.core[]`, `constraints`
|
|
28
|
+
|
|
29
|
+
### 2. La dirección visual elegida
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
cat .sdd/estado.json | grep -E '"design_direction"|"design_system_path"'
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### 3. El DESIGN.md activo
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
DESIGN_PATH=$(cat .sdd/estado.json | node -e "const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8')); console.log(d.design_system_path||'{PLUGIN_DIR}/design-systems/neutral-modern/DESIGN.md')")
|
|
39
|
+
cat "$DESIGN_PATH"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### 4. Las reglas anti-AI-slop
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
cat "{PLUGIN_DIR}/craft/anti-ai-slop.md"
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Lo que produces
|
|
51
|
+
|
|
52
|
+
### ProductDesign JSON
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
{
|
|
56
|
+
"id": "pd-[slug]-001",
|
|
57
|
+
"created_at": "[ISO timestamp]",
|
|
58
|
+
"ir_id": "[id del IR]",
|
|
59
|
+
|
|
60
|
+
"product": {
|
|
61
|
+
"name": "[Nombre del producto — puede refinar el del IR]",
|
|
62
|
+
"tagline": "[Una línea, ≤10 palabras, sin jerga]",
|
|
63
|
+
"value_proposition": "[Por qué existe, en lenguaje del usuario]"
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
"user_flow": [
|
|
67
|
+
"[Paso 1: el usuario llega a la app y ve...]",
|
|
68
|
+
"[Paso 2: hace click en...]",
|
|
69
|
+
"[Paso 3: llena el formulario de...]",
|
|
70
|
+
"[Paso 4: recibe confirmación de...]",
|
|
71
|
+
"[Paso 5: puede volver a ver...]"
|
|
72
|
+
],
|
|
73
|
+
|
|
74
|
+
"core_screens": [
|
|
75
|
+
{
|
|
76
|
+
"name": "[Nombre de pantalla P0]",
|
|
77
|
+
"description": "[Qué hace el usuario aquí]",
|
|
78
|
+
"purpose": "[Por qué esta pantalla existe]",
|
|
79
|
+
"elements": [
|
|
80
|
+
{ "type": "nav", "label": "Navegación principal", "description": "Logo + links principales" },
|
|
81
|
+
{ "type": "hero", "label": "Sección principal", "description": "Valor proposición + CTA" },
|
|
82
|
+
{ "type": "form", "label": "Formulario de [X]", "description": "Campos: nombre, email, [otros]" }
|
|
83
|
+
],
|
|
84
|
+
"priority": "P0"
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"name": "[Nombre de pantalla P1]",
|
|
88
|
+
"...": "...",
|
|
89
|
+
"priority": "P1"
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"name": "[Nombre de pantalla P2]",
|
|
93
|
+
"...": "...",
|
|
94
|
+
"priority": "P2"
|
|
95
|
+
}
|
|
96
|
+
],
|
|
97
|
+
|
|
98
|
+
"mvp_scope": [
|
|
99
|
+
"[Feature 1 — entra en V1]",
|
|
100
|
+
"[Feature 2 — entra en V1]",
|
|
101
|
+
"[Feature 3 — entra en V1]"
|
|
102
|
+
],
|
|
103
|
+
|
|
104
|
+
"out_of_scope": [
|
|
105
|
+
"[Feature que el usuario mencionó pero NO entra en V1]"
|
|
106
|
+
],
|
|
107
|
+
|
|
108
|
+
"design_direction": "[neutral-modern|warm-editorial|bold-brutalist]",
|
|
109
|
+
"design_system_ref": "design-systems/[direction]/DESIGN.md"
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Reglas para definir pantallas
|
|
116
|
+
|
|
117
|
+
### ¿Cuántas pantallas?
|
|
118
|
+
- **Mínimo 3, máximo 5** para el MVP
|
|
119
|
+
- P0: la pantalla más importante — donde el usuario realiza la acción principal
|
|
120
|
+
- P1: soporte directo a P0 (ej: si P0 es "crear reserva", P1 es "ver mis reservas")
|
|
121
|
+
- P2: funcionalidad secundaria (ej: perfil de usuario, configuración)
|
|
122
|
+
|
|
123
|
+
### ¿Qué va en cada pantalla?
|
|
124
|
+
- Define los **elementos** en términos de componentes: `form`, `table`, `card`, `list`, `nav`, `hero`, `chart`, `modal`, `button-group`
|
|
125
|
+
- No uses nombres técnicos: "formulario de cita" no "POST /appointments form"
|
|
126
|
+
- Máximo 5–7 elementos por pantalla (MVP = simple)
|
|
127
|
+
|
|
128
|
+
### ¿Qué entra en el MVP?
|
|
129
|
+
- Solo los `features.core[]` del IR
|
|
130
|
+
- Si un feature tiene ambigüedad, ponlo en P1 o P2, no en P0
|
|
131
|
+
- Lo que está en `features.nice_to_have` del IR va en `out_of_scope`
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Reglas de diseño (del DESIGN.md activo)
|
|
136
|
+
|
|
137
|
+
Lee el DESIGN.md y aplica sus decisiones a tu output:
|
|
138
|
+
|
|
139
|
+
1. **Dirección visual** → mencionarla explícitamente en el JSON y en el mensaje al usuario
|
|
140
|
+
2. **Paleta** → cuando describes elementos, mencionar el color del DESIGN.md (ej: "botón principal en `--accent`")
|
|
141
|
+
3. **Tipografía** → mencionar la fuente display para headings
|
|
142
|
+
4. **Estilo de componentes** → referenciar las reglas del DESIGN.md (ej: "sin border-radius en botones" para bold-brutalist)
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Checklist anti-AI-slop
|
|
147
|
+
|
|
148
|
+
Antes de finalizar el ProductDesign, verifica:
|
|
149
|
+
|
|
150
|
+
- ❌ ¿Usé colores no presentes en el DESIGN.md activo?
|
|
151
|
+
- ❌ ¿Sugerí métricas inventadas ("10x más rápido")?
|
|
152
|
+
- ❌ ¿Propuse emojis como iconos de features?
|
|
153
|
+
- ❌ ¿El copy de las pantallas es copy de relleno genérico?
|
|
154
|
+
- ❌ ¿Los nombres de pantalla son genéricos ("Inicio", "Perfil", "Dashboard") en lugar de específicos del producto?
|
|
155
|
+
|
|
156
|
+
Si alguna respuesta es ✅ (sí lo hice), corrígelo antes de guardar.
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Mensaje al usuario
|
|
161
|
+
|
|
162
|
+
Después de generar el ProductDesign, muestra un resumen legible:
|
|
163
|
+
|
|
164
|
+
```
|
|
165
|
+
═══════════════════════════════════════════
|
|
166
|
+
🎨 DISEÑO DE PRODUCTO
|
|
167
|
+
═══════════════════════════════════════════
|
|
168
|
+
|
|
169
|
+
[product.name]
|
|
170
|
+
"[tagline]"
|
|
171
|
+
|
|
172
|
+
¿Qué hace?
|
|
173
|
+
[value_proposition]
|
|
174
|
+
|
|
175
|
+
Flujo del usuario:
|
|
176
|
+
1. [user_flow[0]]
|
|
177
|
+
2. [user_flow[1]]
|
|
178
|
+
3. [user_flow[2]]
|
|
179
|
+
[...]
|
|
180
|
+
|
|
181
|
+
Pantallas del MVP:
|
|
182
|
+
P0 ★ [screen[0].name]
|
|
183
|
+
[screen[0].description]
|
|
184
|
+
Elementos: [lista de elementos]
|
|
185
|
+
|
|
186
|
+
P1 · [screen[1].name]
|
|
187
|
+
[screen[1].description]
|
|
188
|
+
|
|
189
|
+
P2 · [screen[2].name]
|
|
190
|
+
[screen[2].description]
|
|
191
|
+
|
|
192
|
+
Qué entra en V1:
|
|
193
|
+
✓ [mvp_scope[0]]
|
|
194
|
+
✓ [mvp_scope[1]]
|
|
195
|
+
|
|
196
|
+
Qué queda para después:
|
|
197
|
+
· [out_of_scope[0] si existe]
|
|
198
|
+
|
|
199
|
+
Estilo visual: [design_direction en español]
|
|
200
|
+
[Descripción de 1 línea del DESIGN.md activo]
|
|
201
|
+
|
|
202
|
+
═══════════════════════════════════════════
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## Guardar el output
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
# Guardar ProductDesign JSON
|
|
211
|
+
cat > .sdd/product-design.json << 'PRODUCT_DESIGN'
|
|
212
|
+
[JSON generado]
|
|
213
|
+
PRODUCT_DESIGN
|
|
214
|
+
|
|
215
|
+
# Actualizar estado
|
|
216
|
+
node -e "
|
|
217
|
+
const fs = require('fs');
|
|
218
|
+
const estado = JSON.parse(fs.readFileSync('.sdd/estado.json', 'utf8') || '{}');
|
|
219
|
+
estado.product_design_generado = true;
|
|
220
|
+
fs.writeFileSync('.sdd/estado.json', JSON.stringify(estado, null, 2));
|
|
221
|
+
"
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## Restricciones
|
|
227
|
+
|
|
228
|
+
- **No generas código HTML** — eso es la skill `wireframe-mvp`
|
|
229
|
+
- **No decides el stack técnico** — eso es el agente `architecture-designer`
|
|
230
|
+
- **No escribes specs técnicas** — eso es el mapper `ir-to-spec`
|
|
231
|
+
- Solo defines **qué** se construye y **para quién**, no **cómo**
|
|
232
|
+
- Si algo del IR es ambiguo, haz la decisión de producto más razonable y documéntala en el JSON
|
package/agents/revisor.md
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
---
|
|
2
|
+
name: revisor
|
|
2
3
|
description: Revisor de código senior. Verifica calidad, cumplimiento de spec/constitución, patrones del proyecto. Modelo opus recomendado — la revisión profunda atrapa más bugs.
|
|
3
4
|
model: opus
|
|
4
|
-
|
|
5
|
+
color: pink
|
|
6
|
+
tools: ["Read", "Grep", "Glob", "Bash"]
|
|
5
7
|
---
|
|
6
8
|
|
|
7
9
|
# Agente: Revisor
|
|
@@ -151,3 +153,25 @@ python -m pytest tests/ -v --tb=short 2>/dev/null | tail -20
|
|
|
151
153
|
|
|
152
154
|
**Durante reporte final:**
|
|
153
155
|
- Lite: sin relleno pero frases completas — el usuario lo lee
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Rol en el ciclo Evaluator-Optimizer
|
|
160
|
+
|
|
161
|
+
Cuando `/sdd.implementar` te invoca como **Evaluador** en el ciclo Evaluator-Optimizer (para tareas del Grupo OPUS — arquitecto, critico, seguridad, asesor-datos):
|
|
162
|
+
|
|
163
|
+
1. Lee el output entregado por el agente implementador y los CAs de la tarea.
|
|
164
|
+
2. Puntúa cada CA de **0 a 10**:
|
|
165
|
+
- 10: cubierto completamente, código y test presentes
|
|
166
|
+
- 8-9: cubierto, test menor faltante o edge case no crítico
|
|
167
|
+
- 5-7: cubierto parcialmente (falta manejo de errores, casos borde, etc.)
|
|
168
|
+
- 0-4: no cubierto o implementación incorrecta
|
|
169
|
+
3. Calcula el score promedio.
|
|
170
|
+
4. Si score ≥ 8: responde `EVALUACION: PASA` con score y una línea de resumen.
|
|
171
|
+
5. Si score < 8: responde `EVALUACION: NECESITA_MEJORA` con:
|
|
172
|
+
- Score actual vs umbral (8)
|
|
173
|
+
- CAs que no pasan y razón concreta
|
|
174
|
+
- Feedback específico para el implementador (no genérico)
|
|
175
|
+
|
|
176
|
+
**Limite**: el orquestador controla el número de iteraciones (máx. 3).
|
|
177
|
+
**NO decidas** si la tarea se cancela — emite solo la evaluación y el feedback.
|
package/agents/seguridad.md
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
---
|
|
2
|
+
name: seguridad
|
|
2
3
|
description: Especialista en seguridad de aplicaciones. Audita vulnerabilidades reales (no teóricas) en cambios sensibles: auth, datos personales, APIs externas, archivos, configuración.
|
|
3
4
|
model: opus
|
|
4
|
-
|
|
5
|
+
color: orange
|
|
6
|
+
tools: ["Read", "Grep", "Glob", "Bash"]
|
|
5
7
|
---
|
|
6
8
|
|
|
7
9
|
# Agente: Seguridad
|
|
8
10
|
|
|
9
11
|
Auditas seguridad pragmáticamente. Encuentras vulnerabilidades reales, no falsos positivos.
|
|
10
12
|
|
|
13
|
+
> **Modo de razonamiento**: Razona como un atacante con conocimiento del código. Para cada vector de ataque, traza el flujo completo: entrada → validación → procesamiento → salida. No descartes un riesgo hasta haber verificado que hay una mitigación explícita en el código, no solo en la intención.
|
|
14
|
+
|
|
11
15
|
## Skills obligatorios — leer antes de auditar
|
|
12
16
|
|
|
13
17
|
```bash
|
package/agents/tester.md
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
---
|
|
2
|
+
name: tester
|
|
2
3
|
description: Ingeniero de calidad. Genera tests útiles (que atrapan bugs reales) en cualquier framework. Detecta el framework de tests del proyecto automáticamente.
|
|
3
4
|
model: sonnet
|
|
4
|
-
|
|
5
|
+
color: lime
|
|
6
|
+
tools: ["Read", "Write", "Grep", "Glob", "Bash"]
|
|
5
7
|
---
|
|
6
8
|
|
|
7
9
|
# Agente: Tester
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* agent-memory.js — Hook PostToolUse para memoria persistente + ledger de consumo
|
|
4
|
+
*
|
|
5
|
+
* 1. Memoria por agente: cuando un agente del Grupo OPUS (arquitecto, asesor-datos,
|
|
6
|
+
* disenador-api, critico) escribe un archivo, registra la acción en
|
|
7
|
+
* .sdd/memoria/agente-{nombre}.md para continuidad entre sesiones.
|
|
8
|
+
*
|
|
9
|
+
* 2. Ledger de consumo: para TODOS los agentes, anexa una línea JSONL a
|
|
10
|
+
* .sdd/observabilidad/consumo.jsonl con ts, agente, tool, archivo y bytes.
|
|
11
|
+
* Permite detectar fan-out excesivo y picos de actividad sin coste de tokens.
|
|
12
|
+
*
|
|
13
|
+
* Protocolo de hooks de Claude Code:
|
|
14
|
+
* - Lee el evento JSON desde stdin
|
|
15
|
+
* - Exit 0 → continuar normalmente
|
|
16
|
+
* - Stderr → mensaje visible en el log de Claude Code
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { createInterface } from "node:readline";
|
|
20
|
+
import { existsSync, mkdirSync, appendFileSync, statSync } from "node:fs";
|
|
21
|
+
import { join } from "node:path";
|
|
22
|
+
|
|
23
|
+
const MEMORIA_UMBRAL_BYTES = 50_000; // 50KB — alerta cuando se supera
|
|
24
|
+
|
|
25
|
+
const rl = createInterface({ input: process.stdin, terminal: false });
|
|
26
|
+
let raw = "";
|
|
27
|
+
rl.on("line", (l) => (raw += l + "\n"));
|
|
28
|
+
rl.on("close", () => main(raw.trim()));
|
|
29
|
+
|
|
30
|
+
// Agentes con memoria persistente activada
|
|
31
|
+
const AGENTES_CON_MEMORIA = new Set([
|
|
32
|
+
"arquitecto",
|
|
33
|
+
"asesor-datos",
|
|
34
|
+
"disenador-api",
|
|
35
|
+
"critico",
|
|
36
|
+
]);
|
|
37
|
+
|
|
38
|
+
function detectarAgente() {
|
|
39
|
+
const agente = process.env.CLAUDE_AGENT_NAME ?? "";
|
|
40
|
+
return agente.toLowerCase().trim();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function extraerResumen(contenido) {
|
|
44
|
+
if (!contenido) return "(sin contenido)";
|
|
45
|
+
const lineas = contenido.split("\n").filter((l) => l.trim().length > 10);
|
|
46
|
+
const primera = lineas[0] ?? "";
|
|
47
|
+
return primera.slice(0, 120).trim();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function registrarLedger(cwd, agente, toolName, archivoModificado, contenido) {
|
|
51
|
+
const obsDir = join(cwd, ".sdd", "observabilidad");
|
|
52
|
+
const ledgerFile = join(obsDir, "consumo.jsonl");
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
if (!existsSync(obsDir)) {
|
|
56
|
+
mkdirSync(obsDir, { recursive: true });
|
|
57
|
+
}
|
|
58
|
+
const linea = JSON.stringify({
|
|
59
|
+
ts: new Date().toISOString(),
|
|
60
|
+
agente: agente || "main",
|
|
61
|
+
tool: toolName,
|
|
62
|
+
archivo: archivoModificado,
|
|
63
|
+
bytes: Buffer.byteLength(contenido ?? "", "utf8"),
|
|
64
|
+
});
|
|
65
|
+
appendFileSync(ledgerFile, linea + "\n", "utf8");
|
|
66
|
+
} catch {
|
|
67
|
+
// Silencioso — nunca interrumpir el flujo
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function main(raw) {
|
|
72
|
+
let event;
|
|
73
|
+
try {
|
|
74
|
+
event = JSON.parse(raw);
|
|
75
|
+
} catch {
|
|
76
|
+
process.exit(0);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const toolName = event?.tool_name ?? "";
|
|
80
|
+
if (toolName !== "Write" && toolName !== "Edit" && toolName !== "MultiEdit") {
|
|
81
|
+
process.exit(0);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const agente = detectarAgente();
|
|
85
|
+
const cwd = process.cwd();
|
|
86
|
+
const archivoModificado =
|
|
87
|
+
event?.tool_input?.file_path ??
|
|
88
|
+
event?.tool_input?.path ??
|
|
89
|
+
"(desconocido)";
|
|
90
|
+
const contenido =
|
|
91
|
+
event?.tool_input?.content ??
|
|
92
|
+
event?.tool_input?.new_string ??
|
|
93
|
+
"";
|
|
94
|
+
|
|
95
|
+
// ── Ledger JSONL (aplica a TODOS los agentes) ──────────────────────────────
|
|
96
|
+
registrarLedger(cwd, agente, toolName, archivoModificado, contenido);
|
|
97
|
+
|
|
98
|
+
// ── Memoria persistente (solo agentes del grupo OPUS) ──────────────────────
|
|
99
|
+
if (!agente || !AGENTES_CON_MEMORIA.has(agente)) {
|
|
100
|
+
process.exit(0);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const memoriaDir = join(cwd, ".sdd", "memoria");
|
|
104
|
+
const memoriaFile = join(memoriaDir, `agente-${agente}.md`);
|
|
105
|
+
|
|
106
|
+
if (!existsSync(memoriaDir)) {
|
|
107
|
+
try {
|
|
108
|
+
mkdirSync(memoriaDir, { recursive: true });
|
|
109
|
+
} catch {
|
|
110
|
+
process.exit(0);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const fecha = new Date().toISOString().slice(0, 10);
|
|
115
|
+
const resumen = extraerResumen(contenido);
|
|
116
|
+
|
|
117
|
+
if (!existsSync(memoriaFile)) {
|
|
118
|
+
const header =
|
|
119
|
+
`# Memoria del agente: ${agente}\n\n` +
|
|
120
|
+
`Este archivo registra automáticamente las decisiones y cambios del agente.\n` +
|
|
121
|
+
`Léelo al inicio de cada sesión para mantener continuidad entre conversaciones.\n\n` +
|
|
122
|
+
`---\n\n`;
|
|
123
|
+
try {
|
|
124
|
+
appendFileSync(memoriaFile, header, "utf8");
|
|
125
|
+
} catch {
|
|
126
|
+
process.exit(0);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const entrada = `## ${fecha} — ${archivoModificado}\n> ${resumen}\n\n`;
|
|
131
|
+
|
|
132
|
+
try {
|
|
133
|
+
appendFileSync(memoriaFile, entrada, "utf8");
|
|
134
|
+
process.stderr.write(
|
|
135
|
+
`🧠 [agent-memory] Registrado en memoria de ${agente}: ${archivoModificado}\n`
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
// Alerta de tamaño — no bloquea el flujo, solo informa
|
|
139
|
+
try {
|
|
140
|
+
const { size } = statSync(memoriaFile);
|
|
141
|
+
if (size > MEMORIA_UMBRAL_BYTES) {
|
|
142
|
+
process.stderr.write(
|
|
143
|
+
`⚠️ [agent-memory] Memoria de ${agente} supera ${Math.round(size / 1024)}KB — considera ejecutar /sdd.optimizar memoria\n`
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
} catch {
|
|
147
|
+
// Silencioso
|
|
148
|
+
}
|
|
149
|
+
} catch {
|
|
150
|
+
// Silencioso
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
process.exit(0);
|
|
154
|
+
}
|
package/cli/index.js
CHANGED
|
@@ -26,7 +26,6 @@ import { join, dirname } from "node:path";
|
|
|
26
26
|
import { fileURLToPath } from "node:url";
|
|
27
27
|
import { homedir } from "node:os";
|
|
28
28
|
import { execSync } from "node:child_process";
|
|
29
|
-
|
|
30
29
|
// ─── Paths ────────────────────────────────────────────────────────────────────
|
|
31
30
|
|
|
32
31
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
@@ -355,7 +354,7 @@ function cmdDoctor() {
|
|
|
355
354
|
|
|
356
355
|
function uso() {
|
|
357
356
|
console.log(`
|
|
358
|
-
SDD-ES — CLI
|
|
357
|
+
SDD-ES — CLI (v${pluginVersion()})
|
|
359
358
|
|
|
360
359
|
Uso:
|
|
361
360
|
npx sdd-es init [--global] Instala el plugin (proyecto o global)
|
package/commands/sdd.analizar.md
CHANGED
|
@@ -28,9 +28,20 @@ cat .sdd/dominio/glosario.md 2>/dev/null
|
|
|
28
28
|
ls .sdd/arquitectura/ 2>/dev/null
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
## PASO 1.5 —
|
|
31
|
+
## PASO 1.5 — Model routing para dimensiones
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
Aplica el mismo routing de modelos que `/sdd.implementar` al despachar las dimensiones de análisis:
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
Grupo OPUS → análisis de constitución, seguridad y arquitectura (D1, D5, D7)
|
|
37
|
+
Grupo SONNET → análisis de spec, plan, tareas y glosario (D2, D3, D4, D6)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Cuando PTC está disponible, el routing se aplica a cada subagente en el bloque paralelo.
|
|
41
|
+
|
|
42
|
+
## PASO 1.6 — Despacho PTC de dimensiones
|
|
43
|
+
|
|
44
|
+
Las 7 dimensiones de auditoría son **independientes entre sí** — cada una lee los mismos artefactos sin modificarlos. Esto las hace candidatas ideales para PTC (skill `orquestacion-ptc`). El modelo de cada subagente sigue el routing del PASO 1.5.
|
|
34
45
|
|
|
35
46
|
**Si hay ≥3 agentes disponibles para ejecutar el análisis en paralelo:**
|
|
36
47
|
|
|
@@ -237,5 +248,15 @@ Empieza con:
|
|
|
237
248
|
/sdd.[comando del primer bloqueante]
|
|
238
249
|
```
|
|
239
250
|
|
|
251
|
+
## Output styles
|
|
252
|
+
|
|
253
|
+
Si el argumento contiene `pm`, `arq` o `dev`, adapta el reporte del PASO 3:
|
|
254
|
+
|
|
255
|
+
**Modo `pm`:** Solo veredicto, número de bloqueantes y recomendación de acción. Sin dimensiones técnicas ni matrices.
|
|
256
|
+
|
|
257
|
+
**Modo `arq`:** Enfatiza las dimensiones 1 (Constitución↔Plan) y 5 (Tareas internas). Incluye la matriz de cobertura CAs→Tareas y el grafo de dependencias.
|
|
258
|
+
|
|
259
|
+
**Modo `dev`:** El reporte completo del PASO 3 con todas las dimensiones, matrices y distribución de agentes (comportamiento actual).
|
|
260
|
+
|
|
240
261
|
---
|
|
241
262
|
**HOOK:** `.sdd/hooks/despues_analizar.sh`
|