elsabro 2.0.0 → 2.1.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/README.md +6 -6
- package/bin/install.js +14 -3
- package/commands/elsabro/execute.md +218 -50
- package/commands/elsabro/pause-work.md +56 -0
- package/commands/elsabro/resume-work.md +111 -2
- package/commands/elsabro/verify-work.md +167 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -22,19 +22,19 @@ ELSABRO es un sistema de desarrollo AI-powered para Claude Code que te guía pas
|
|
|
22
22
|
|
|
23
23
|
## Instalación
|
|
24
24
|
|
|
25
|
-
###
|
|
25
|
+
### Con NPX (Recomendado)
|
|
26
26
|
```bash
|
|
27
|
-
npx
|
|
27
|
+
npx elsabro --global
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
### Con PNPM
|
|
31
31
|
```bash
|
|
32
|
-
pnpm dlx
|
|
32
|
+
pnpm dlx elsabro --global
|
|
33
33
|
```
|
|
34
34
|
|
|
35
35
|
### Con BUN
|
|
36
36
|
```bash
|
|
37
|
-
bunx
|
|
37
|
+
bunx elsabro --global
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
Después de instalar, abre Claude Code y escribe:
|
|
@@ -221,7 +221,7 @@ Voy a crear tu blog con:
|
|
|
221
221
|
## Actualización
|
|
222
222
|
|
|
223
223
|
```bash
|
|
224
|
-
npx
|
|
224
|
+
npx elsabro --update
|
|
225
225
|
```
|
|
226
226
|
|
|
227
227
|
O desde Claude Code:
|
|
@@ -232,7 +232,7 @@ O desde Claude Code:
|
|
|
232
232
|
## Desinstalación
|
|
233
233
|
|
|
234
234
|
```bash
|
|
235
|
-
npx
|
|
235
|
+
npx elsabro --uninstall
|
|
236
236
|
```
|
|
237
237
|
|
|
238
238
|
## Estructura del Proyecto
|
package/bin/install.js
CHANGED
|
@@ -397,9 +397,20 @@ async function install() {
|
|
|
397
397
|
}
|
|
398
398
|
}
|
|
399
399
|
|
|
400
|
-
//
|
|
401
|
-
|
|
402
|
-
|
|
400
|
+
// Clean up any empty hooks structure from previous installations
|
|
401
|
+
// Claude Code rejects empty postToolUse arrays/objects
|
|
402
|
+
if (settings.hooks) {
|
|
403
|
+
const ptu = settings.hooks.postToolUse;
|
|
404
|
+
const isEmptyArray = Array.isArray(ptu) && ptu.length === 0;
|
|
405
|
+
const isEmptyObject = ptu && typeof ptu === 'object' && !Array.isArray(ptu) && Object.keys(ptu).length === 0;
|
|
406
|
+
if (isEmptyArray || isEmptyObject) {
|
|
407
|
+
delete settings.hooks.postToolUse;
|
|
408
|
+
}
|
|
409
|
+
// Remove hooks object entirely if empty
|
|
410
|
+
if (Object.keys(settings.hooks).length === 0) {
|
|
411
|
+
delete settings.hooks;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
403
414
|
|
|
404
415
|
// Add version tracking
|
|
405
416
|
settings.elsabro = {
|
|
@@ -9,6 +9,10 @@ allowed-tools:
|
|
|
9
9
|
- Glob
|
|
10
10
|
- Grep
|
|
11
11
|
- Task
|
|
12
|
+
- TaskCreate
|
|
13
|
+
- TaskUpdate
|
|
14
|
+
- TaskList
|
|
15
|
+
- TaskGet
|
|
12
16
|
- mcp__plugin_context7_context7__*
|
|
13
17
|
argument-hint: "[número de fase]"
|
|
14
18
|
---
|
|
@@ -17,10 +21,11 @@ argument-hint: "[número de fase]"
|
|
|
17
21
|
|
|
18
22
|
<objective>
|
|
19
23
|
Ejecutar planes de una fase con:
|
|
24
|
+
- **Sistema de Tasks para tracking real** de waves y dependencias
|
|
20
25
|
- Investigación de patrones con Context7
|
|
21
26
|
- TDD cuando sea apropiado
|
|
22
27
|
- Commits atómicos por tarea
|
|
23
|
-
- Verificación automática
|
|
28
|
+
- Verificación automática con agregador
|
|
24
29
|
</objective>
|
|
25
30
|
|
|
26
31
|
<process>
|
|
@@ -32,48 +37,137 @@ ls .planning/*-PLAN.md
|
|
|
32
37
|
|
|
33
38
|
Encontrar planes para la fase especificada.
|
|
34
39
|
|
|
35
|
-
## Paso 2:
|
|
40
|
+
## Paso 2: Crear Estructura de Tasks
|
|
36
41
|
|
|
42
|
+
### 2.1 Crear Task coordinadora de fase
|
|
43
|
+
```javascript
|
|
44
|
+
TaskCreate({
|
|
45
|
+
subject: "Execute Phase [N]",
|
|
46
|
+
description: "Coordinar ejecución de todos los planes de la fase",
|
|
47
|
+
activeForm: "Ejecutando Fase [N]...",
|
|
48
|
+
metadata: { phase: N, type: "coordinator" }
|
|
49
|
+
}) // → phase-coordinator-id
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 2.2 Organizar por Waves y crear Tasks
|
|
37
53
|
Leer frontmatter de cada plan para agrupar por `wave`:
|
|
38
54
|
|
|
55
|
+
```javascript
|
|
56
|
+
// Para cada wave, crear task coordinadora
|
|
57
|
+
TaskCreate({
|
|
58
|
+
subject: "Execute Wave [W]",
|
|
59
|
+
description: "Plans: A, B, C en paralelo",
|
|
60
|
+
activeForm: "Ejecutando Wave [W]...",
|
|
61
|
+
metadata: { wave: W, plans: ["A", "B", "C"] }
|
|
62
|
+
}) // → wave-W-id
|
|
63
|
+
|
|
64
|
+
// Wave 2+ tiene dependencia de wave anterior
|
|
65
|
+
TaskUpdate({
|
|
66
|
+
taskId: "wave-2-id",
|
|
67
|
+
addBlockedBy: ["wave-1-id"]
|
|
68
|
+
})
|
|
39
69
|
```
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
70
|
+
|
|
71
|
+
### 2.3 Crear Tasks por plan dentro de cada wave
|
|
72
|
+
```javascript
|
|
73
|
+
TaskCreate({
|
|
74
|
+
subject: "Execute Plan [name]",
|
|
75
|
+
description: "TDD + commits para plan específico",
|
|
76
|
+
activeForm: "Ejecutando Plan [name]...",
|
|
77
|
+
metadata: { wave: W, plan: "name", type: "executor" }
|
|
78
|
+
}) // → plan-X-id
|
|
79
|
+
|
|
80
|
+
// Bloquear por wave coordinator
|
|
81
|
+
TaskUpdate({
|
|
82
|
+
taskId: "plan-X-id",
|
|
83
|
+
addBlockedBy: ["wave-W-id"]
|
|
84
|
+
})
|
|
43
85
|
```
|
|
44
86
|
|
|
45
|
-
## Paso 3: Ejecutar Waves
|
|
87
|
+
## Paso 3: Ejecutar Waves con Tracking
|
|
46
88
|
|
|
47
89
|
Para cada wave:
|
|
48
90
|
|
|
49
|
-
###
|
|
91
|
+
### Marcar wave como in_progress
|
|
92
|
+
```javascript
|
|
93
|
+
TaskUpdate({ taskId: "wave-W-id", status: "in_progress" })
|
|
50
94
|
```
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
95
|
+
|
|
96
|
+
### Si hay múltiples planes en la wave → Paralelo
|
|
97
|
+
```javascript
|
|
98
|
+
// Marcar todos los planes como in_progress
|
|
99
|
+
TaskUpdate({ taskId: "plan-A-id", status: "in_progress" })
|
|
100
|
+
TaskUpdate({ taskId: "plan-B-id", status: "in_progress" })
|
|
101
|
+
TaskUpdate({ taskId: "plan-C-id", status: "in_progress" })
|
|
102
|
+
|
|
103
|
+
// Lanzar agentes en paralelo (UN SOLO MENSAJE)
|
|
104
|
+
Task(elsabro-executor) para Plan A |
|
|
105
|
+
Task(elsabro-executor) para Plan B |
|
|
106
|
+
Task(elsabro-executor) para Plan C
|
|
107
|
+
|
|
108
|
+
// Al completar cada plan
|
|
109
|
+
TaskUpdate({ taskId: "plan-A-id", status: "completed" })
|
|
54
110
|
```
|
|
55
111
|
|
|
56
112
|
### Si solo hay un plan → Secuencial
|
|
57
|
-
```
|
|
113
|
+
```javascript
|
|
114
|
+
TaskUpdate({ taskId: "plan-X-id", status: "in_progress" })
|
|
58
115
|
Task(elsabro-executor) para Plan único
|
|
116
|
+
TaskUpdate({ taskId: "plan-X-id", status: "completed" })
|
|
59
117
|
```
|
|
60
118
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
-
|
|
64
|
-
|
|
65
|
-
|
|
119
|
+
### Marcar wave como completed cuando todos sus planes terminen
|
|
120
|
+
```javascript
|
|
121
|
+
TaskUpdate({ taskId: "wave-W-id", status: "completed" })
|
|
122
|
+
// → Wave W+1 se desbloquea automáticamente
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Paso 4: Verificar Fase (con Agregador)
|
|
126
|
+
|
|
127
|
+
### 4.1 Crear tasks de verificación
|
|
128
|
+
```javascript
|
|
129
|
+
TaskCreate({
|
|
130
|
+
subject: "Verify Functional Requirements",
|
|
131
|
+
activeForm: "Verificando funcionalidad...",
|
|
132
|
+
metadata: { type: "verifier", area: "functional" }
|
|
133
|
+
}) // → verify-functional-id
|
|
134
|
+
|
|
135
|
+
TaskCreate({
|
|
136
|
+
subject: "Verify Quality Metrics",
|
|
137
|
+
activeForm: "Verificando calidad...",
|
|
138
|
+
metadata: { type: "verifier", area: "quality" }
|
|
139
|
+
}) // → verify-quality-id
|
|
140
|
+
|
|
141
|
+
TaskCreate({
|
|
142
|
+
subject: "Verify Phase Completion",
|
|
143
|
+
activeForm: "Agregando resultados...",
|
|
144
|
+
metadata: { type: "aggregator" }
|
|
145
|
+
}) // → verify-aggregate-id
|
|
146
|
+
|
|
147
|
+
// Agregador espera a todos los verificadores
|
|
148
|
+
TaskUpdate({
|
|
149
|
+
taskId: "verify-aggregate-id",
|
|
150
|
+
addBlockedBy: ["verify-functional-id", "verify-quality-id"]
|
|
151
|
+
})
|
|
152
|
+
```
|
|
66
153
|
|
|
67
|
-
|
|
154
|
+
### 4.2 Ejecutar verificación en paralelo
|
|
155
|
+
```javascript
|
|
156
|
+
TaskUpdate({ taskId: "verify-functional-id", status: "in_progress" })
|
|
157
|
+
TaskUpdate({ taskId: "verify-quality-id", status: "in_progress" })
|
|
68
158
|
|
|
69
|
-
|
|
159
|
+
// Lanzar agentes verificadores en paralelo
|
|
160
|
+
Task(elsabro-verifier): Verifica funcionalidad |
|
|
161
|
+
Task(elsabro-verifier): Verifica calidad
|
|
70
162
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
163
|
+
// Marcar completed al terminar
|
|
164
|
+
TaskUpdate({ taskId: "verify-functional-id", status: "completed" })
|
|
165
|
+
TaskUpdate({ taskId: "verify-quality-id", status: "completed" })
|
|
166
|
+
|
|
167
|
+
// Agregador se desbloquea y genera reporte final
|
|
168
|
+
TaskUpdate({ taskId: "verify-aggregate-id", status: "in_progress" })
|
|
169
|
+
// ... genera VERIFICATION.md ...
|
|
170
|
+
TaskUpdate({ taskId: "verify-aggregate-id", status: "completed" })
|
|
77
171
|
```
|
|
78
172
|
|
|
79
173
|
## Paso 5: Manejar Resultados
|
|
@@ -163,24 +257,59 @@ git commit -m "feat([fase]-[plan]): [descripción]"
|
|
|
163
257
|
</execution_protocol>
|
|
164
258
|
|
|
165
259
|
<parallel_execution>
|
|
166
|
-
## Ejecución Paralela
|
|
260
|
+
## Ejecución Paralela con Tasks
|
|
167
261
|
|
|
168
262
|
### Cuándo usar paralelo
|
|
169
263
|
- Múltiples planes en la misma wave
|
|
170
264
|
- Tareas independientes (sin dependencias)
|
|
171
265
|
|
|
172
|
-
### Cómo paralelizar
|
|
266
|
+
### Cómo paralelizar CON TRACKING
|
|
267
|
+
```javascript
|
|
268
|
+
// 1. Crear tasks para cada plan
|
|
269
|
+
const planATask = TaskCreate({ subject: "Plan A", activeForm: "Ejecutando Plan A..." })
|
|
270
|
+
const planBTask = TaskCreate({ subject: "Plan B", activeForm: "Ejecutando Plan B..." })
|
|
271
|
+
const planCTask = TaskCreate({ subject: "Plan C", activeForm: "Ejecutando Plan C..." })
|
|
272
|
+
|
|
273
|
+
// 2. Marcar todas como in_progress
|
|
274
|
+
TaskUpdate({ taskId: planATask.id, status: "in_progress" })
|
|
275
|
+
TaskUpdate({ taskId: planBTask.id, status: "in_progress" })
|
|
276
|
+
TaskUpdate({ taskId: planCTask.id, status: "in_progress" })
|
|
277
|
+
|
|
278
|
+
// 3. Lanzar agentes EN UN SOLO MENSAJE
|
|
279
|
+
Task(elsabro-executor) Plan A |
|
|
280
|
+
Task(elsabro-executor) Plan B |
|
|
281
|
+
Task(elsabro-executor) Plan C
|
|
282
|
+
|
|
283
|
+
// 4. Al completar cada uno
|
|
284
|
+
TaskUpdate({ taskId: planATask.id, status: "completed" })
|
|
285
|
+
// ...
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Visualización automática (Ctrl+T)
|
|
173
289
|
```
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
290
|
+
📋 Execute Phase 3:
|
|
291
|
+
✅ Wave 1 - Completed (3/3 plans)
|
|
292
|
+
🔧 Wave 2 - Executing Plan D... (1/2 plans done)
|
|
293
|
+
✅ Plan D - Completed
|
|
294
|
+
⏳ Plan E - In Progress
|
|
295
|
+
⏳ Wave 3 - Blocked by Wave 2
|
|
296
|
+
⏳ Verification - Blocked by Wave 3
|
|
178
297
|
```
|
|
179
298
|
|
|
180
299
|
### Cuándo NO paralelizar
|
|
181
|
-
- Planes con dependencias entre sí
|
|
300
|
+
- Planes con dependencias entre sí (usar `blockedBy`)
|
|
182
301
|
- Plan 2 necesita output de Plan 1
|
|
183
302
|
- Modifican los mismos archivos
|
|
303
|
+
|
|
304
|
+
### Expresar dependencias entre planes
|
|
305
|
+
```javascript
|
|
306
|
+
// Plan B depende de Plan A
|
|
307
|
+
TaskUpdate({
|
|
308
|
+
taskId: "plan-B-id",
|
|
309
|
+
addBlockedBy: ["plan-A-id"]
|
|
310
|
+
})
|
|
311
|
+
// Plan B no puede empezar hasta que Plan A complete
|
|
312
|
+
```
|
|
184
313
|
</parallel_execution>
|
|
185
314
|
|
|
186
315
|
<error_handling>
|
|
@@ -248,27 +377,66 @@ Este comando usa **policy: quorum** por defecto.
|
|
|
248
377
|
| Tests fallan | HIGH | Debug o skip |
|
|
249
378
|
| Lint warnings | MEDIUM | Continuar |
|
|
250
379
|
|
|
251
|
-
### Actualizar Estado
|
|
252
|
-
|
|
253
|
-
Después de errores, actualizar
|
|
254
|
-
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
"
|
|
380
|
+
### Actualizar Estado con Tasks
|
|
381
|
+
|
|
382
|
+
Después de errores, actualizar tanto SESSION-STATE.json como Tasks:
|
|
383
|
+
|
|
384
|
+
```javascript
|
|
385
|
+
// 1. Actualizar task con metadata de error
|
|
386
|
+
TaskUpdate({
|
|
387
|
+
taskId: "plan-X-id",
|
|
388
|
+
metadata: {
|
|
389
|
+
error: {
|
|
390
|
+
code: "TESTS_FAILED",
|
|
391
|
+
severity: "HIGH",
|
|
392
|
+
at: "2024-01-20T15:25:00Z",
|
|
393
|
+
attempt: 3,
|
|
394
|
+
maxAttempts: 3
|
|
264
395
|
}
|
|
265
|
-
},
|
|
266
|
-
"retry": {
|
|
267
|
-
"currentAttempt": 3,
|
|
268
|
-
"maxAttempts": 3,
|
|
269
|
-
"exhausted": true
|
|
270
396
|
}
|
|
271
|
-
}
|
|
397
|
+
})
|
|
398
|
+
|
|
399
|
+
// 2. Si retry exhausted, NO marcar completed
|
|
400
|
+
// Crear subtask de fix
|
|
401
|
+
TaskCreate({
|
|
402
|
+
subject: "Fix: Tests failing in Plan X",
|
|
403
|
+
description: "3 retry attempts exhausted, needs manual fix",
|
|
404
|
+
activeForm: "Fixing test failures...",
|
|
405
|
+
metadata: { type: "bugfix", parentPlan: "plan-X-id" }
|
|
406
|
+
}) // → bugfix-id
|
|
407
|
+
|
|
408
|
+
// 3. Bloquear verificación hasta que bugfix complete
|
|
409
|
+
TaskUpdate({
|
|
410
|
+
taskId: "verify-aggregate-id",
|
|
411
|
+
addBlockedBy: ["bugfix-id"]
|
|
412
|
+
})
|
|
413
|
+
|
|
414
|
+
// 4. También actualizar SESSION-STATE.json para compatibilidad
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
### Rollback de Estado con Tasks
|
|
418
|
+
|
|
419
|
+
Si necesitas volver a ejecutar un plan:
|
|
420
|
+
|
|
421
|
+
```javascript
|
|
422
|
+
// Volver plan a in_progress (no crear nuevo)
|
|
423
|
+
TaskUpdate({ taskId: "plan-X-id", status: "in_progress" })
|
|
424
|
+
|
|
425
|
+
// Re-ejecutar
|
|
426
|
+
Task(elsabro-executor) para Plan X
|
|
427
|
+
|
|
428
|
+
// Marcar completed cuando funcione
|
|
429
|
+
TaskUpdate({ taskId: "plan-X-id", status: "completed" })
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
### Ver Estado Actual
|
|
433
|
+
|
|
434
|
+
```javascript
|
|
435
|
+
// Listar todas las tasks
|
|
436
|
+
TaskList()
|
|
437
|
+
|
|
438
|
+
// Ver detalles de una task específica
|
|
439
|
+
TaskGet({ taskId: "plan-X-id" })
|
|
272
440
|
```
|
|
273
441
|
</error_handling>
|
|
274
442
|
|
|
@@ -6,6 +6,10 @@ allowed-tools:
|
|
|
6
6
|
- Write
|
|
7
7
|
- Bash
|
|
8
8
|
- Glob
|
|
9
|
+
- TaskUpdate
|
|
10
|
+
- TaskCreate
|
|
11
|
+
- TaskList
|
|
12
|
+
- TaskGet
|
|
9
13
|
---
|
|
10
14
|
|
|
11
15
|
# /elsabro:pause-work
|
|
@@ -16,6 +20,41 @@ allowed-tools:
|
|
|
16
20
|
|
|
17
21
|
Guardar el estado actual del trabajo para poder retomarlo fácilmente después. Captura contexto, notas y próximos pasos.
|
|
18
22
|
|
|
23
|
+
## Integración con Tasks API
|
|
24
|
+
|
|
25
|
+
Al pausar, se actualiza el estado en el sistema de Tasks para persistencia y fácil recuperación:
|
|
26
|
+
|
|
27
|
+
```javascript
|
|
28
|
+
// 1. Obtener task activa actual
|
|
29
|
+
TaskList() // Ver qué está in_progress
|
|
30
|
+
|
|
31
|
+
// 2. Actualizar task con estado de pausa
|
|
32
|
+
TaskUpdate({
|
|
33
|
+
taskId: "current-phase-task-id",
|
|
34
|
+
metadata: {
|
|
35
|
+
status: "paused",
|
|
36
|
+
pausedAt: "2024-01-20T17:30:00Z",
|
|
37
|
+
expectedReturn: "2024-01-21T09:00:00Z",
|
|
38
|
+
lastCompletedSubtask: "validation-implementation",
|
|
39
|
+
nextSubtask: "avatar-upload",
|
|
40
|
+
notes: "Zod schema completo, falta avatar",
|
|
41
|
+
uncommittedFiles: 3
|
|
42
|
+
}
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
// 3. Crear reminder task (opcional)
|
|
46
|
+
TaskCreate({
|
|
47
|
+
subject: "Resume: User profile page",
|
|
48
|
+
description: "Paused on 2024-01-20, expected return tomorrow morning",
|
|
49
|
+
activeForm: "Waiting to resume...",
|
|
50
|
+
metadata: {
|
|
51
|
+
type: "reminder",
|
|
52
|
+
pausedTaskId: "current-phase-task-id",
|
|
53
|
+
dueDate: "2024-01-21T09:00:00Z"
|
|
54
|
+
}
|
|
55
|
+
})
|
|
56
|
+
```
|
|
57
|
+
|
|
19
58
|
## Uso
|
|
20
59
|
|
|
21
60
|
```bash
|
|
@@ -178,9 +217,26 @@ Choice (1/2/3):
|
|
|
178
217
|
## Integración
|
|
179
218
|
|
|
180
219
|
- Paired con `/elsabro:resume-work`
|
|
220
|
+
- **Tasks API** para persistencia de estado entre sesiones
|
|
181
221
|
- Optional git integration (commit/stash)
|
|
182
222
|
- Session file tracked in `.planning/`
|
|
183
223
|
|
|
224
|
+
### Flujo Completo con Tasks
|
|
225
|
+
|
|
226
|
+
```javascript
|
|
227
|
+
// Al pausar:
|
|
228
|
+
// 1. Guardar SESSION.md (humano-legible)
|
|
229
|
+
// 2. Guardar SESSION-STATE.json (agente-legible)
|
|
230
|
+
// 3. TaskUpdate con metadata de pausa
|
|
231
|
+
// 4. TaskCreate reminder (opcional)
|
|
232
|
+
|
|
233
|
+
// Al reanudar (/elsabro:resume-work):
|
|
234
|
+
// 1. TaskGet para recuperar metadata de pausa
|
|
235
|
+
// 2. Validar integridad del contexto
|
|
236
|
+
// 3. TaskUpdate para reactivar task
|
|
237
|
+
// 4. TaskDelete reminder si existe
|
|
238
|
+
```
|
|
239
|
+
|
|
184
240
|
<session_state_management>
|
|
185
241
|
## Gestión de Estado de Sesión
|
|
186
242
|
|
|
@@ -7,6 +7,10 @@ allowed-tools:
|
|
|
7
7
|
- Bash
|
|
8
8
|
- Glob
|
|
9
9
|
- Grep
|
|
10
|
+
- TaskGet
|
|
11
|
+
- TaskUpdate
|
|
12
|
+
- TaskList
|
|
13
|
+
- TaskCreate
|
|
10
14
|
---
|
|
11
15
|
|
|
12
16
|
# /elsabro:resume-work
|
|
@@ -15,7 +19,50 @@ allowed-tools:
|
|
|
15
19
|
|
|
16
20
|
## Propósito
|
|
17
21
|
|
|
18
|
-
Retomar trabajo en un proyecto después de una interrupción. Reconstruye contexto, muestra estado actual y sugiere siguiente paso.
|
|
22
|
+
Retomar trabajo en un proyecto después de una interrupción. Reconstruye contexto desde Tasks API, muestra estado actual y sugiere siguiente paso.
|
|
23
|
+
|
|
24
|
+
## Integración con Tasks API
|
|
25
|
+
|
|
26
|
+
Al reanudar, primero consultar el sistema de Tasks para recuperar contexto:
|
|
27
|
+
|
|
28
|
+
```javascript
|
|
29
|
+
// 1. Listar todas las tasks para ver estado actual
|
|
30
|
+
TaskList()
|
|
31
|
+
// Output:
|
|
32
|
+
// ⏸ User profile page - Paused (metadata.status: "paused")
|
|
33
|
+
// ✅ Dashboard layout - Completed
|
|
34
|
+
// ⏳ Settings modal - Pending
|
|
35
|
+
|
|
36
|
+
// 2. Obtener detalles de la task pausada
|
|
37
|
+
TaskGet({ taskId: "paused-task-id" })
|
|
38
|
+
// Output:
|
|
39
|
+
// status: "in_progress" (pero metadata.status: "paused")
|
|
40
|
+
// metadata: {
|
|
41
|
+
// pausedAt: "2024-01-20T17:30:00Z",
|
|
42
|
+
// expectedReturn: "2024-01-21T09:00:00Z",
|
|
43
|
+
// lastCompletedSubtask: "validation-implementation",
|
|
44
|
+
// nextSubtask: "avatar-upload",
|
|
45
|
+
// notes: "Zod schema completo, falta avatar"
|
|
46
|
+
// }
|
|
47
|
+
|
|
48
|
+
// 3. Validar integridad del contexto
|
|
49
|
+
// - ¿Tiempo desde pausa > 7 días? → Warning
|
|
50
|
+
// - ¿Tiempo > 30 días? → Sugerir revisión completa
|
|
51
|
+
// - ¿Archivos referenciados aún existen?
|
|
52
|
+
|
|
53
|
+
// 4. Reactivar task
|
|
54
|
+
TaskUpdate({
|
|
55
|
+
taskId: "paused-task-id",
|
|
56
|
+
metadata: {
|
|
57
|
+
status: "active", // Ya no está pausada
|
|
58
|
+
resumedAt: "2024-01-21T09:15:00Z",
|
|
59
|
+
resumedFrom: "pause"
|
|
60
|
+
}
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
// 5. Eliminar reminder si existe
|
|
64
|
+
TaskUpdate({ taskId: "reminder-task-id", status: "deleted" })
|
|
65
|
+
```
|
|
19
66
|
|
|
20
67
|
## Uso
|
|
21
68
|
|
|
@@ -151,9 +198,71 @@ Implementing user profile validation
|
|
|
151
198
|
## Integración
|
|
152
199
|
|
|
153
200
|
- Paired con `/elsabro:pause-work`
|
|
154
|
-
-
|
|
201
|
+
- **Tasks API** como fuente primaria de estado
|
|
202
|
+
- Uses session data from `.planning/SESSION.md` como fallback
|
|
155
203
|
- Can trigger `/elsabro:progress` for overview
|
|
156
204
|
|
|
205
|
+
### Flujo de Recuperación con Tasks
|
|
206
|
+
|
|
207
|
+
```javascript
|
|
208
|
+
// Prioridad de fuentes de contexto:
|
|
209
|
+
// 1. Tasks API (TaskGet) → Más confiable, persistente entre sesiones
|
|
210
|
+
// 2. SESSION-STATE.json → Backup para detalles adicionales
|
|
211
|
+
// 3. SESSION.md → Fallback humano-legible
|
|
212
|
+
|
|
213
|
+
async function resumeWork() {
|
|
214
|
+
// 1. Intentar recuperar de Tasks
|
|
215
|
+
const tasks = await TaskList()
|
|
216
|
+
const pausedTask = tasks.find(t => t.metadata?.status === "paused")
|
|
217
|
+
|
|
218
|
+
if (pausedTask) {
|
|
219
|
+
const details = await TaskGet({ taskId: pausedTask.id })
|
|
220
|
+
|
|
221
|
+
// Reactivar task principal
|
|
222
|
+
await TaskUpdate({
|
|
223
|
+
taskId: pausedTask.id,
|
|
224
|
+
metadata: { ...details.metadata, status: "active", resumedAt: new Date() }
|
|
225
|
+
})
|
|
226
|
+
|
|
227
|
+
// Buscar y eliminar reminder task asociada
|
|
228
|
+
const reminderTask = tasks.find(t =>
|
|
229
|
+
t.metadata?.type === "reminder" &&
|
|
230
|
+
t.metadata?.pausedTaskId === pausedTask.id
|
|
231
|
+
)
|
|
232
|
+
if (reminderTask) {
|
|
233
|
+
await TaskUpdate({ taskId: reminderTask.id, status: "deleted" })
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Mostrar metadatos recuperados al usuario
|
|
237
|
+
console.log(`Recovered context:
|
|
238
|
+
- Last completed: ${details.metadata.lastCompletedSubtask}
|
|
239
|
+
- Next step: ${details.metadata.nextSubtask}
|
|
240
|
+
- Notes: ${details.metadata.notes}
|
|
241
|
+
`)
|
|
242
|
+
|
|
243
|
+
return details
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// 2. Fallback a SESSION-STATE.json
|
|
247
|
+
if (fs.existsSync('.planning/SESSION-STATE.json')) {
|
|
248
|
+
// ... recuperar de archivo ...
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// 3. Fallback final a SESSION.md
|
|
252
|
+
// ...
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Ventajas de Tasks API para Resume
|
|
257
|
+
|
|
258
|
+
| Aspecto | Antes (archivos) | Ahora (Tasks API) |
|
|
259
|
+
|---------|------------------|-------------------|
|
|
260
|
+
| Persistencia | Solo en proyecto | Entre sesiones |
|
|
261
|
+
| Recuperación | Parse manual | TaskGet directo |
|
|
262
|
+
| Integridad | Validar JSON | Sistema garantiza |
|
|
263
|
+
| Visibilidad | Leer archivo | Ctrl+T nativo |
|
|
264
|
+
| Staleness | Calcular manual | Metadata timestamps |
|
|
265
|
+
|
|
157
266
|
<session_validation>
|
|
158
267
|
## Validación de Sesión
|
|
159
268
|
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: verify-work
|
|
3
|
-
description: Verificación completa del trabajo realizado usando agentes paralelos
|
|
3
|
+
description: Verificación completa del trabajo realizado usando agentes paralelos con Tasks
|
|
4
4
|
allowed-tools:
|
|
5
5
|
- Read
|
|
6
6
|
- Bash
|
|
7
7
|
- Glob
|
|
8
8
|
- Grep
|
|
9
9
|
- Task
|
|
10
|
+
- TaskCreate
|
|
11
|
+
- TaskUpdate
|
|
12
|
+
- TaskList
|
|
13
|
+
- TaskGet
|
|
10
14
|
---
|
|
11
15
|
|
|
12
16
|
# /elsabro:verify-work
|
|
@@ -17,29 +21,75 @@ allowed-tools:
|
|
|
17
21
|
|
|
18
22
|
Verificar que el trabajo completado cumple con los requirements, pasa todos los tests, y está listo para merge/deploy.
|
|
19
23
|
|
|
24
|
+
## Sistema de Tasks para Verificación
|
|
25
|
+
|
|
26
|
+
### Crear estructura de verificación con dependencias
|
|
27
|
+
|
|
28
|
+
```javascript
|
|
29
|
+
// 1. Crear tasks de verificación paralela
|
|
30
|
+
TaskCreate({
|
|
31
|
+
subject: "Verify Functional Requirements",
|
|
32
|
+
description: "Check acceptance criteria and feature behavior",
|
|
33
|
+
activeForm: "Verificando funcionalidad...",
|
|
34
|
+
metadata: { type: "verifier", area: "functional", timeout: 30 }
|
|
35
|
+
}) // → functional-id
|
|
36
|
+
|
|
37
|
+
TaskCreate({
|
|
38
|
+
subject: "Verify Quality Metrics",
|
|
39
|
+
description: "Run tests, check coverage, lint",
|
|
40
|
+
activeForm: "Verificando calidad...",
|
|
41
|
+
metadata: { type: "verifier", area: "quality", timeout: 45 }
|
|
42
|
+
}) // → quality-id
|
|
43
|
+
|
|
44
|
+
TaskCreate({
|
|
45
|
+
subject: "Verify Security & Edge Cases",
|
|
46
|
+
description: "Check vulnerabilities, error handling",
|
|
47
|
+
activeForm: "Verificando seguridad...",
|
|
48
|
+
metadata: { type: "verifier", area: "security", timeout: 25 }
|
|
49
|
+
}) // → security-id
|
|
50
|
+
|
|
51
|
+
// 2. Crear agregador que espera a todos
|
|
52
|
+
TaskCreate({
|
|
53
|
+
subject: "Aggregate Verification Results",
|
|
54
|
+
description: "Combine results and generate final report",
|
|
55
|
+
activeForm: "Agregando resultados...",
|
|
56
|
+
metadata: { type: "aggregator", policy: "fail_fast" }
|
|
57
|
+
}) // → aggregate-id
|
|
58
|
+
|
|
59
|
+
// 3. Configurar dependencias (agregador espera a todos)
|
|
60
|
+
TaskUpdate({
|
|
61
|
+
taskId: "aggregate-id",
|
|
62
|
+
addBlockedBy: ["functional-id", "quality-id", "security-id"]
|
|
63
|
+
})
|
|
64
|
+
```
|
|
65
|
+
|
|
20
66
|
## Protocolo de Verificación
|
|
21
67
|
|
|
22
68
|
Usa **mínimo 3 agentes en paralelo** para verificación exhaustiva:
|
|
23
69
|
|
|
24
70
|
```
|
|
25
71
|
┌──────────────────────────────────────────────────────┐
|
|
26
|
-
│ VERIFICACIÓN PARALELA
|
|
72
|
+
│ VERIFICACIÓN PARALELA CON TASKS │
|
|
27
73
|
├──────────────────────────────────────────────────────┤
|
|
28
74
|
│ │
|
|
29
|
-
│
|
|
75
|
+
│ Task: Functional Verification (verify-functional) │
|
|
30
76
|
│ └─ ¿El código hace lo que debe? │
|
|
31
77
|
│ └─ ¿Cumple acceptance criteria? │
|
|
32
78
|
│ │
|
|
33
|
-
│
|
|
79
|
+
│ Task: Quality Verification (verify-quality) │
|
|
34
80
|
│ └─ ¿Tests pasan? │
|
|
35
81
|
│ └─ ¿Coverage adecuado? │
|
|
36
82
|
│ └─ ¿Sin errores de lint? │
|
|
37
83
|
│ │
|
|
38
|
-
│
|
|
84
|
+
│ Task: Security/Edge Cases (verify-security) │
|
|
39
85
|
│ └─ ¿Sin vulnerabilidades obvias? │
|
|
40
86
|
│ └─ ¿Edge cases manejados? │
|
|
41
87
|
│ └─ ¿Error handling correcto? │
|
|
42
88
|
│ │
|
|
89
|
+
│ Task: Aggregator (blockedBy: [all above]) │
|
|
90
|
+
│ └─ Se desbloquea cuando TODOS completen │
|
|
91
|
+
│ └─ Genera VERIFICATION-REPORT.md │
|
|
92
|
+
│ │
|
|
43
93
|
└──────────────────────────────────────────────────────┘
|
|
44
94
|
```
|
|
45
95
|
|
|
@@ -146,22 +196,60 @@ Para verificación, usamos `policy: fail_fast` porque todos los checks son crít
|
|
|
146
196
|
└────────────────────────────────────────────────┘
|
|
147
197
|
```
|
|
148
198
|
|
|
149
|
-
### Lanzamiento de Agentes
|
|
199
|
+
### Lanzamiento de Agentes con Tasks
|
|
200
|
+
|
|
201
|
+
```javascript
|
|
202
|
+
// 1. Marcar todos como in_progress
|
|
203
|
+
TaskUpdate({ taskId: "functional-id", status: "in_progress" })
|
|
204
|
+
TaskUpdate({ taskId: "quality-id", status: "in_progress" })
|
|
205
|
+
TaskUpdate({ taskId: "security-id", status: "in_progress" })
|
|
206
|
+
|
|
207
|
+
// 2. Lanzar agentes EN UN SOLO MENSAJE (paralelo real)
|
|
208
|
+
Task(elsabro-verifier, model: "opus"): Verify functional requirements |
|
|
209
|
+
Task(elsabro-verifier, model: "opus"): Verify quality metrics |
|
|
210
|
+
Task(elsabro-verifier, model: "opus"): Verify security and edge cases
|
|
211
|
+
|
|
212
|
+
// 3. Al completar cada uno, marcar completed
|
|
213
|
+
TaskUpdate({
|
|
214
|
+
taskId: "functional-id",
|
|
215
|
+
status: "completed",
|
|
216
|
+
metadata: { result: "PASS", duration: "18s" }
|
|
217
|
+
})
|
|
218
|
+
// ... repeat for others ...
|
|
219
|
+
|
|
220
|
+
// 4. Cuando TODOS completen, aggregator se desbloquea automáticamente
|
|
221
|
+
TaskUpdate({ taskId: "aggregate-id", status: "in_progress" })
|
|
222
|
+
// ... generate VERIFICATION-REPORT.md ...
|
|
223
|
+
TaskUpdate({ taskId: "aggregate-id", status: "completed" })
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Visualización con Ctrl+T
|
|
150
227
|
|
|
151
228
|
```
|
|
152
|
-
|
|
229
|
+
📋 Verification Tasks:
|
|
230
|
+
✅ Functional Verification - PASS (18s)
|
|
231
|
+
✅ Quality Verification - PASS (25s)
|
|
232
|
+
🔧 Security Verification - Running...
|
|
233
|
+
⏳ Aggregate Results - Blocked (waiting for security)
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Diagrama de Dependencias
|
|
237
|
+
|
|
238
|
+
```
|
|
239
|
+
# Los 3 agentes corren en paralelo, agregador espera
|
|
153
240
|
┌─────────────────────────────────────────────────┐
|
|
154
241
|
│ │
|
|
155
242
|
│ ┌─────────────┐ ┌─────────────┐ ┌─────────┐ │
|
|
156
243
|
│ │ Functional │ │ Quality │ │Security │ │
|
|
157
|
-
│ │
|
|
244
|
+
│ │ (Task) │ │ (Task) │ │(Task) │ │
|
|
158
245
|
│ └──────┬──────┘ └──────┬──────┘ └────┬────┘ │
|
|
159
246
|
│ │ │ │ │
|
|
160
|
-
│
|
|
247
|
+
│ └───── blockedBy ┼──────────────┘ │
|
|
161
248
|
│ │ │
|
|
162
249
|
│ ┌──────▼──────┐ │
|
|
163
250
|
│ │ Aggregator │ │
|
|
164
|
-
│ │ (
|
|
251
|
+
│ │ (Task) │ │
|
|
252
|
+
│ │ auto-unlock │ │
|
|
165
253
|
│ └─────────────┘ │
|
|
166
254
|
│ │
|
|
167
255
|
└─────────────────────────────────────────────────┘
|
|
@@ -238,9 +326,70 @@ Si un agente falla por razones transitorias (timeout, network):
|
|
|
238
326
|
└──────────────────────────────────────────────────┘
|
|
239
327
|
```
|
|
240
328
|
|
|
241
|
-
### Actualizar Estado
|
|
329
|
+
### Actualizar Estado con Tasks
|
|
330
|
+
|
|
331
|
+
Al completar verificación, actualizar tanto Tasks como SESSION-STATE.json:
|
|
332
|
+
|
|
333
|
+
```javascript
|
|
334
|
+
// 1. Verificar estado final con TaskList
|
|
335
|
+
TaskList()
|
|
336
|
+
// Output:
|
|
337
|
+
// ✅ functional-verifier: completed
|
|
338
|
+
// ✅ quality-verifier: completed
|
|
339
|
+
// ✅ security-verifier: completed
|
|
340
|
+
// ✅ aggregate-results: completed
|
|
341
|
+
|
|
342
|
+
// 2. Obtener detalles de cualquier task
|
|
343
|
+
TaskGet({ taskId: "quality-id" })
|
|
344
|
+
// Output:
|
|
345
|
+
// status: "completed"
|
|
346
|
+
// metadata: { result: "PASS", tests: "45/45", coverage: "87%" }
|
|
347
|
+
|
|
348
|
+
// 3. Si alguna falló, TaskGet muestra detalles
|
|
349
|
+
TaskGet({ taskId: "security-id" })
|
|
350
|
+
// Output:
|
|
351
|
+
// status: "completed"
|
|
352
|
+
// metadata: { result: "FAIL", vulnerabilities: ["SQL injection in /api/users"] }
|
|
353
|
+
```
|
|
242
354
|
|
|
243
|
-
|
|
355
|
+
### Manejo de Fallo con Tasks
|
|
356
|
+
|
|
357
|
+
```javascript
|
|
358
|
+
// Si quality-verifier falla:
|
|
359
|
+
TaskUpdate({
|
|
360
|
+
taskId: "quality-id",
|
|
361
|
+
status: "completed", // Completó pero con error
|
|
362
|
+
metadata: {
|
|
363
|
+
result: "FAIL",
|
|
364
|
+
failedTests: 3,
|
|
365
|
+
details: ["Profile.test.ts: Expected John got null"]
|
|
366
|
+
}
|
|
367
|
+
})
|
|
368
|
+
|
|
369
|
+
// El agregador se activa pero reporta el fallo
|
|
370
|
+
TaskUpdate({ taskId: "aggregate-id", status: "in_progress" })
|
|
371
|
+
// Genera VERIFICATION-REPORT.md con detalles del fallo
|
|
372
|
+
TaskUpdate({
|
|
373
|
+
taskId: "aggregate-id",
|
|
374
|
+
status: "completed",
|
|
375
|
+
metadata: {
|
|
376
|
+
overallResult: "FAIL",
|
|
377
|
+
passedChecks: 2,
|
|
378
|
+
failedChecks: 1,
|
|
379
|
+
readyForReview: false
|
|
380
|
+
}
|
|
381
|
+
})
|
|
382
|
+
|
|
383
|
+
// Crear subtask de fix si es necesario
|
|
384
|
+
TaskCreate({
|
|
385
|
+
subject: "Fix: Quality verification failed",
|
|
386
|
+
description: "3 tests failing, needs attention",
|
|
387
|
+
activeForm: "Fixing test failures...",
|
|
388
|
+
metadata: { type: "bugfix", parentTask: "quality-id" }
|
|
389
|
+
})
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
### JSON State (compatibilidad)
|
|
244
393
|
|
|
245
394
|
```json
|
|
246
395
|
{
|
|
@@ -263,6 +412,12 @@ Al completar verificación:
|
|
|
263
412
|
"lastRun": "2024-01-20T16:30:00Z",
|
|
264
413
|
"result": "PASS",
|
|
265
414
|
"readyForReview": true
|
|
415
|
+
},
|
|
416
|
+
"tasks": {
|
|
417
|
+
"functional-id": "completed",
|
|
418
|
+
"quality-id": "completed",
|
|
419
|
+
"security-id": "completed",
|
|
420
|
+
"aggregate-id": "completed"
|
|
266
421
|
}
|
|
267
422
|
}
|
|
268
423
|
```
|