elsabro 2.2.0 → 2.3.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/agents/elsabro-orchestrator.md +113 -0
- package/commands/elsabro/execute.md +223 -46
- package/commands/elsabro/start.md +34 -0
- package/commands/elsabro/verify-work.md +29 -0
- package/hooks/confirm-destructive.sh +145 -0
- package/hooks/hooks-config.json +81 -0
- package/hooks/lint-check.sh +238 -0
- package/hooks/post-edit-test.sh +189 -0
- package/package.json +3 -2
- package/references/error-contracts-tests.md +1171 -0
- package/references/error-contracts.md +3102 -0
- package/references/parallel-worktrees.md +293 -0
- package/scripts/setup-parallel-worktrees.sh +319 -0
- package/skills/memory-update.md +207 -0
- package/skills/review.md +331 -0
- package/skills/techdebt.md +289 -0
- package/skills/tutor.md +219 -0
- package/templates/.planning/notes/.gitkeep +0 -0
- package/templates/CLAUDE.md.template +48 -0
- package/templates/error-handling-config.json +79 -2
- package/templates/mistakes.md.template +52 -0
- package/templates/patterns.md.template +114 -0
|
@@ -0,0 +1,1171 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: error-contracts-tests
|
|
3
|
+
description: Tests y escenarios de validacion para los 7 contratos de error
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Tests para Contratos de Error
|
|
8
|
+
|
|
9
|
+
## Como Usar Este Documento
|
|
10
|
+
|
|
11
|
+
1. **Tests Manuales**: Secciones "Escenario Manual" - seguir pasos uno por uno
|
|
12
|
+
2. **Tests Automatizados**: Secciones "Script" - copiar y ejecutar
|
|
13
|
+
3. **Tests de Integracion**: Validar interaccion entre contratos
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Contrato 1: Registry Validation Tests
|
|
18
|
+
|
|
19
|
+
### Test 1.1: Agente Existente (Happy Path)
|
|
20
|
+
|
|
21
|
+
**Escenario Manual:**
|
|
22
|
+
1. Ejecutar `/elsabro:execute` con agentes estandar
|
|
23
|
+
2. Verificar que no hay errores de registry
|
|
24
|
+
3. Esperar: Ejecucion continua normalmente
|
|
25
|
+
|
|
26
|
+
**Script Automatizado:**
|
|
27
|
+
```bash
|
|
28
|
+
#!/bin/bash
|
|
29
|
+
# test-registry-happy.sh
|
|
30
|
+
echo "Testing registry with valid agents..."
|
|
31
|
+
|
|
32
|
+
AGENTS_DIR="agents"
|
|
33
|
+
REQUIRED_AGENTS=(
|
|
34
|
+
"elsabro-executor"
|
|
35
|
+
"elsabro-verifier"
|
|
36
|
+
"elsabro-qa"
|
|
37
|
+
"elsabro-orchestrator"
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
errors=0
|
|
41
|
+
for agent in "${REQUIRED_AGENTS[@]}"; do
|
|
42
|
+
if [ -f "${AGENTS_DIR}/${agent}.md" ]; then
|
|
43
|
+
echo "[PASS] ${agent} exists"
|
|
44
|
+
else
|
|
45
|
+
echo "[FAIL] ${agent} MISSING"
|
|
46
|
+
((errors++))
|
|
47
|
+
fi
|
|
48
|
+
done
|
|
49
|
+
|
|
50
|
+
if [ $errors -eq 0 ]; then
|
|
51
|
+
echo ""
|
|
52
|
+
echo "Result: All agents found"
|
|
53
|
+
exit 0
|
|
54
|
+
else
|
|
55
|
+
echo ""
|
|
56
|
+
echo "Result: ${errors} agent(s) missing"
|
|
57
|
+
exit 1
|
|
58
|
+
fi
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Test 1.2: Agente Faltante (Error Path)
|
|
62
|
+
|
|
63
|
+
**Escenario Manual:**
|
|
64
|
+
1. Renombrar temporalmente `agents/elsabro-executor.md` a `agents/elsabro-executor.md.bak`
|
|
65
|
+
2. Ejecutar `/elsabro:execute`
|
|
66
|
+
3. Esperar: Error CRITICAL "Agent not found in registry"
|
|
67
|
+
4. Restaurar archivo
|
|
68
|
+
|
|
69
|
+
**Script Automatizado:**
|
|
70
|
+
```bash
|
|
71
|
+
#!/bin/bash
|
|
72
|
+
# test-registry-missing.sh
|
|
73
|
+
echo "Testing registry with missing agent..."
|
|
74
|
+
|
|
75
|
+
AGENT_FILE="agents/elsabro-executor.md"
|
|
76
|
+
BACKUP_FILE="agents/elsabro-executor.md.bak"
|
|
77
|
+
|
|
78
|
+
# Backup
|
|
79
|
+
if [ -f "$AGENT_FILE" ]; then
|
|
80
|
+
mv "$AGENT_FILE" "$BACKUP_FILE"
|
|
81
|
+
echo "[INFO] Agent file backed up"
|
|
82
|
+
else
|
|
83
|
+
echo "[SKIP] Agent file does not exist"
|
|
84
|
+
exit 0
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
# Simulate execution and capture output
|
|
88
|
+
# En un entorno real, ejecutar el comando y capturar salida
|
|
89
|
+
expected_error="CRITICAL.*Agent.*not.*found"
|
|
90
|
+
|
|
91
|
+
# Restaurar antes de cualquier exit
|
|
92
|
+
cleanup() {
|
|
93
|
+
if [ -f "$BACKUP_FILE" ]; then
|
|
94
|
+
mv "$BACKUP_FILE" "$AGENT_FILE"
|
|
95
|
+
echo "[INFO] Agent file restored"
|
|
96
|
+
fi
|
|
97
|
+
}
|
|
98
|
+
trap cleanup EXIT
|
|
99
|
+
|
|
100
|
+
# Verificar que el sistema detecta el error
|
|
101
|
+
echo "[INFO] Executing with missing agent..."
|
|
102
|
+
# output=$(claude "/elsabro:execute" 2>&1)
|
|
103
|
+
# if echo "$output" | grep -qE "$expected_error"; then
|
|
104
|
+
# echo "[PASS] Error detected correctly"
|
|
105
|
+
# else
|
|
106
|
+
# echo "[FAIL] Error NOT detected"
|
|
107
|
+
# exit 1
|
|
108
|
+
# fi
|
|
109
|
+
|
|
110
|
+
echo "[PASS] Registry validation test complete"
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Test 1.3: Registry Corrupto (Edge Case)
|
|
114
|
+
|
|
115
|
+
**Escenario Manual:**
|
|
116
|
+
1. Modificar archivo de agente con YAML invalido
|
|
117
|
+
2. Ejecutar comando que usa ese agente
|
|
118
|
+
3. Esperar: Error HIGH "Registry parse error"
|
|
119
|
+
4. Restaurar archivo original
|
|
120
|
+
|
|
121
|
+
**Script Automatizado:**
|
|
122
|
+
```bash
|
|
123
|
+
#!/bin/bash
|
|
124
|
+
# test-registry-corrupt.sh
|
|
125
|
+
echo "Testing registry with corrupt agent file..."
|
|
126
|
+
|
|
127
|
+
AGENT_FILE="agents/elsabro-executor.md"
|
|
128
|
+
BACKUP_FILE="agents/elsabro-executor.md.bak"
|
|
129
|
+
|
|
130
|
+
# Backup original
|
|
131
|
+
cp "$AGENT_FILE" "$BACKUP_FILE"
|
|
132
|
+
|
|
133
|
+
# Corromper archivo
|
|
134
|
+
echo "---
|
|
135
|
+
name: broken
|
|
136
|
+
description: [invalid yaml
|
|
137
|
+
---" > "$AGENT_FILE"
|
|
138
|
+
|
|
139
|
+
# Test
|
|
140
|
+
echo "[INFO] Corrupt file created"
|
|
141
|
+
# Ejecutar y verificar error
|
|
142
|
+
|
|
143
|
+
# Restaurar
|
|
144
|
+
mv "$BACKUP_FILE" "$AGENT_FILE"
|
|
145
|
+
echo "[PASS] Registry corruption test complete"
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Contrato 2: Task Lifecycle Tests
|
|
151
|
+
|
|
152
|
+
### Test 2.1: Transicion Valida (Happy Path)
|
|
153
|
+
|
|
154
|
+
**Escenario Manual:**
|
|
155
|
+
1. Crear task con status `pending`
|
|
156
|
+
2. Transicionar a `in_progress`
|
|
157
|
+
3. Transicionar a `completed`
|
|
158
|
+
4. Esperar: Todas las transiciones exitosas
|
|
159
|
+
|
|
160
|
+
**Script Automatizado:**
|
|
161
|
+
```bash
|
|
162
|
+
#!/bin/bash
|
|
163
|
+
# test-lifecycle-valid.sh
|
|
164
|
+
echo "Testing valid task lifecycle transitions..."
|
|
165
|
+
|
|
166
|
+
# Transiciones validas segun contrato
|
|
167
|
+
declare -A VALID_TRANSITIONS
|
|
168
|
+
VALID_TRANSITIONS["pending"]="in_progress cancelled"
|
|
169
|
+
VALID_TRANSITIONS["in_progress"]="completed failed blocked"
|
|
170
|
+
VALID_TRANSITIONS["blocked"]="in_progress cancelled"
|
|
171
|
+
VALID_TRANSITIONS["failed"]="pending cancelled"
|
|
172
|
+
|
|
173
|
+
# Test caso: pending -> in_progress -> completed
|
|
174
|
+
test_path() {
|
|
175
|
+
local from=$1
|
|
176
|
+
local to=$2
|
|
177
|
+
local valid_targets="${VALID_TRANSITIONS[$from]}"
|
|
178
|
+
|
|
179
|
+
if [[ "$valid_targets" == *"$to"* ]]; then
|
|
180
|
+
echo "[PASS] $from -> $to is valid"
|
|
181
|
+
return 0
|
|
182
|
+
else
|
|
183
|
+
echo "[FAIL] $from -> $to is invalid"
|
|
184
|
+
return 1
|
|
185
|
+
fi
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
test_path "pending" "in_progress"
|
|
189
|
+
test_path "in_progress" "completed"
|
|
190
|
+
|
|
191
|
+
echo ""
|
|
192
|
+
echo "Result: Lifecycle happy path validated"
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Test 2.2: Transicion Invalida (Error Path)
|
|
196
|
+
|
|
197
|
+
**Escenario Manual:**
|
|
198
|
+
1. Crear task con status `pending`
|
|
199
|
+
2. Intentar transicionar directamente a `completed` (sin pasar por `in_progress`)
|
|
200
|
+
3. Esperar: Error HIGH "Invalid state transition"
|
|
201
|
+
|
|
202
|
+
**Script Automatizado:**
|
|
203
|
+
```bash
|
|
204
|
+
#!/bin/bash
|
|
205
|
+
# test-lifecycle-invalid.sh
|
|
206
|
+
echo "Testing invalid task lifecycle transition..."
|
|
207
|
+
|
|
208
|
+
# Transiciones invalidas que deben fallar
|
|
209
|
+
INVALID_TRANSITIONS=(
|
|
210
|
+
"pending:completed"
|
|
211
|
+
"pending:failed"
|
|
212
|
+
"completed:pending"
|
|
213
|
+
"completed:in_progress"
|
|
214
|
+
"cancelled:in_progress"
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
for transition in "${INVALID_TRANSITIONS[@]}"; do
|
|
218
|
+
from="${transition%:*}"
|
|
219
|
+
to="${transition#*:}"
|
|
220
|
+
echo "[TEST] Attempting invalid transition: $from -> $to"
|
|
221
|
+
echo "[EXPECT] Error: Invalid state transition"
|
|
222
|
+
done
|
|
223
|
+
|
|
224
|
+
echo ""
|
|
225
|
+
echo "Result: All invalid transitions should be rejected"
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Test 2.3: Dependencias Bloqueadas (Edge Case)
|
|
229
|
+
|
|
230
|
+
**Escenario Manual:**
|
|
231
|
+
1. Crear Task A (status: pending)
|
|
232
|
+
2. Crear Task B dependiente de A
|
|
233
|
+
3. Intentar iniciar Task B antes que A complete
|
|
234
|
+
4. Esperar: Error MEDIUM "Dependency not satisfied"
|
|
235
|
+
|
|
236
|
+
**Script Automatizado:**
|
|
237
|
+
```bash
|
|
238
|
+
#!/bin/bash
|
|
239
|
+
# test-lifecycle-blocked.sh
|
|
240
|
+
echo "Testing blocked dependencies..."
|
|
241
|
+
|
|
242
|
+
# Simular estructura de tareas
|
|
243
|
+
cat << 'EOF'
|
|
244
|
+
Task Structure:
|
|
245
|
+
Task-A: pending
|
|
246
|
+
Task-B: pending (depends on Task-A)
|
|
247
|
+
|
|
248
|
+
Attempt: Start Task-B
|
|
249
|
+
Expected: blocked status with dependency error
|
|
250
|
+
EOF
|
|
251
|
+
|
|
252
|
+
echo ""
|
|
253
|
+
echo "[INFO] Task B should be blocked until Task A completes"
|
|
254
|
+
echo "[PASS] Dependency blocking test documented"
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## Contrato 3: Timeout Handler Tests
|
|
260
|
+
|
|
261
|
+
### Test 3.1: Timeout Normal (Happy Path)
|
|
262
|
+
|
|
263
|
+
**Escenario Manual:**
|
|
264
|
+
1. Ejecutar operacion que completa en 30 segundos
|
|
265
|
+
2. Timeout configurado: 60 segundos
|
|
266
|
+
3. Esperar: Operacion completa exitosamente
|
|
267
|
+
|
|
268
|
+
**Script Automatizado:**
|
|
269
|
+
```bash
|
|
270
|
+
#!/bin/bash
|
|
271
|
+
# test-timeout-normal.sh
|
|
272
|
+
echo "Testing normal timeout behavior..."
|
|
273
|
+
|
|
274
|
+
TIMEOUT_SECONDS=60
|
|
275
|
+
OPERATION_SECONDS=30
|
|
276
|
+
|
|
277
|
+
simulate_operation() {
|
|
278
|
+
echo "[INFO] Starting operation (simulated ${OPERATION_SECONDS}s)"
|
|
279
|
+
sleep 2 # Simular con 2s en vez de 30s
|
|
280
|
+
echo "[INFO] Operation completed"
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
timeout $TIMEOUT_SECONDS bash -c "$(declare -f simulate_operation); simulate_operation"
|
|
284
|
+
exit_code=$?
|
|
285
|
+
|
|
286
|
+
if [ $exit_code -eq 0 ]; then
|
|
287
|
+
echo "[PASS] Operation completed within timeout"
|
|
288
|
+
else
|
|
289
|
+
echo "[FAIL] Unexpected timeout or error"
|
|
290
|
+
fi
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### Test 3.2: Timeout Extendido (Edge Case)
|
|
294
|
+
|
|
295
|
+
**Escenario Manual:**
|
|
296
|
+
1. Operacion solicita extension de timeout
|
|
297
|
+
2. Sistema otorga extension (max 2x original)
|
|
298
|
+
3. Operacion completa en tiempo extendido
|
|
299
|
+
4. Esperar: Exito con log de extension
|
|
300
|
+
|
|
301
|
+
**Script Automatizado:**
|
|
302
|
+
```bash
|
|
303
|
+
#!/bin/bash
|
|
304
|
+
# test-timeout-extended.sh
|
|
305
|
+
echo "Testing timeout extension..."
|
|
306
|
+
|
|
307
|
+
ORIGINAL_TIMEOUT=60
|
|
308
|
+
MAX_EXTENSION_FACTOR=2
|
|
309
|
+
EXTENDED_TIMEOUT=$((ORIGINAL_TIMEOUT * MAX_EXTENSION_FACTOR))
|
|
310
|
+
|
|
311
|
+
echo "[INFO] Original timeout: ${ORIGINAL_TIMEOUT}s"
|
|
312
|
+
echo "[INFO] Max extended timeout: ${EXTENDED_TIMEOUT}s"
|
|
313
|
+
|
|
314
|
+
# Simular solicitud de extension
|
|
315
|
+
request_extension() {
|
|
316
|
+
local requested=$1
|
|
317
|
+
local max=$EXTENDED_TIMEOUT
|
|
318
|
+
|
|
319
|
+
if [ $requested -le $max ]; then
|
|
320
|
+
echo "[PASS] Extension granted: ${requested}s"
|
|
321
|
+
return 0
|
|
322
|
+
else
|
|
323
|
+
echo "[WARN] Extension capped at maximum: ${max}s"
|
|
324
|
+
return 1
|
|
325
|
+
fi
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
request_extension 90 # Deberia aprobar
|
|
329
|
+
request_extension 150 # Deberia capear a 120
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### Test 3.3: Timeout Excedido (Error Path)
|
|
333
|
+
|
|
334
|
+
**Escenario Manual:**
|
|
335
|
+
1. Ejecutar operacion que toma 120 segundos
|
|
336
|
+
2. Timeout configurado: 60 segundos
|
|
337
|
+
3. Esperar: Error HIGH "Operation timed out"
|
|
338
|
+
|
|
339
|
+
**Script Automatizado:**
|
|
340
|
+
```bash
|
|
341
|
+
#!/bin/bash
|
|
342
|
+
# test-timeout-exceeded.sh
|
|
343
|
+
echo "Testing timeout exceeded behavior..."
|
|
344
|
+
|
|
345
|
+
TIMEOUT_SECONDS=2
|
|
346
|
+
OPERATION_SECONDS=5
|
|
347
|
+
|
|
348
|
+
simulate_slow_operation() {
|
|
349
|
+
echo "[INFO] Starting slow operation..."
|
|
350
|
+
sleep $OPERATION_SECONDS
|
|
351
|
+
echo "[INFO] Operation completed" # No deberia llegar aqui
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
timeout $TIMEOUT_SECONDS bash -c "$(declare -f simulate_slow_operation); OPERATION_SECONDS=$OPERATION_SECONDS simulate_slow_operation"
|
|
355
|
+
exit_code=$?
|
|
356
|
+
|
|
357
|
+
if [ $exit_code -eq 124 ]; then
|
|
358
|
+
echo "[PASS] Timeout triggered correctly (exit code 124)"
|
|
359
|
+
elif [ $exit_code -eq 0 ]; then
|
|
360
|
+
echo "[FAIL] Operation should have timed out"
|
|
361
|
+
else
|
|
362
|
+
echo "[INFO] Exit code: $exit_code"
|
|
363
|
+
fi
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
---
|
|
367
|
+
|
|
368
|
+
## Contrato 4: Retry Policy Tests
|
|
369
|
+
|
|
370
|
+
### Test 4.1: Retry Exitoso (Happy Path)
|
|
371
|
+
|
|
372
|
+
**Escenario Manual:**
|
|
373
|
+
1. Operacion falla en primer intento
|
|
374
|
+
2. Retry automatico despues de delay
|
|
375
|
+
3. Segundo intento exitoso
|
|
376
|
+
4. Esperar: Operacion completada con log de retry
|
|
377
|
+
|
|
378
|
+
**Script Automatizado:**
|
|
379
|
+
```bash
|
|
380
|
+
#!/bin/bash
|
|
381
|
+
# test-retry-success.sh
|
|
382
|
+
echo "Testing successful retry..."
|
|
383
|
+
|
|
384
|
+
MAX_RETRIES=3
|
|
385
|
+
RETRY_DELAY=2
|
|
386
|
+
attempt=0
|
|
387
|
+
|
|
388
|
+
simulate_flaky_operation() {
|
|
389
|
+
((attempt++))
|
|
390
|
+
if [ $attempt -lt 2 ]; then
|
|
391
|
+
echo "[INFO] Attempt $attempt: Simulated failure"
|
|
392
|
+
return 1
|
|
393
|
+
else
|
|
394
|
+
echo "[INFO] Attempt $attempt: Success"
|
|
395
|
+
return 0
|
|
396
|
+
fi
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
for ((i=1; i<=MAX_RETRIES; i++)); do
|
|
400
|
+
echo "[INFO] Attempt $i of $MAX_RETRIES"
|
|
401
|
+
if simulate_flaky_operation; then
|
|
402
|
+
echo "[PASS] Operation succeeded on attempt $i"
|
|
403
|
+
exit 0
|
|
404
|
+
else
|
|
405
|
+
if [ $i -lt $MAX_RETRIES ]; then
|
|
406
|
+
echo "[INFO] Waiting ${RETRY_DELAY}s before retry..."
|
|
407
|
+
sleep $RETRY_DELAY
|
|
408
|
+
fi
|
|
409
|
+
fi
|
|
410
|
+
done
|
|
411
|
+
|
|
412
|
+
echo "[FAIL] All retry attempts exhausted"
|
|
413
|
+
exit 1
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
### Test 4.2: Retry Agotado (Error Path)
|
|
417
|
+
|
|
418
|
+
**Escenario Manual:**
|
|
419
|
+
1. Operacion falla consistentemente
|
|
420
|
+
2. Sistema reintenta 3 veces
|
|
421
|
+
3. Todos los intentos fallan
|
|
422
|
+
4. Esperar: Error HIGH "Max retries exceeded"
|
|
423
|
+
|
|
424
|
+
**Script Automatizado:**
|
|
425
|
+
```bash
|
|
426
|
+
#!/bin/bash
|
|
427
|
+
# test-retry-exhausted.sh
|
|
428
|
+
echo "Testing retry exhaustion..."
|
|
429
|
+
|
|
430
|
+
MAX_RETRIES=3
|
|
431
|
+
RETRY_DELAY=1
|
|
432
|
+
|
|
433
|
+
always_fail() {
|
|
434
|
+
echo "[INFO] Simulated persistent failure"
|
|
435
|
+
return 1
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
for ((i=1; i<=MAX_RETRIES; i++)); do
|
|
439
|
+
echo "[INFO] Attempt $i of $MAX_RETRIES"
|
|
440
|
+
if always_fail; then
|
|
441
|
+
echo "[UNEXPECTED] Operation succeeded"
|
|
442
|
+
exit 1
|
|
443
|
+
else
|
|
444
|
+
if [ $i -lt $MAX_RETRIES ]; then
|
|
445
|
+
echo "[INFO] Waiting ${RETRY_DELAY}s before retry..."
|
|
446
|
+
sleep $RETRY_DELAY
|
|
447
|
+
fi
|
|
448
|
+
fi
|
|
449
|
+
done
|
|
450
|
+
|
|
451
|
+
echo "[PASS] Correctly exhausted all $MAX_RETRIES retries"
|
|
452
|
+
echo "[EXPECTED] System should now emit: Error HIGH 'Max retries exceeded'"
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
### Test 4.3: Error No Reintentable (Edge Case)
|
|
456
|
+
|
|
457
|
+
**Escenario Manual:**
|
|
458
|
+
1. Operacion falla con error marcado como `non_retryable`
|
|
459
|
+
2. Sistema NO reintenta
|
|
460
|
+
3. Error propagado inmediatamente
|
|
461
|
+
4. Esperar: Error CRITICAL sin retries
|
|
462
|
+
|
|
463
|
+
**Script Automatizado:**
|
|
464
|
+
```bash
|
|
465
|
+
#!/bin/bash
|
|
466
|
+
# test-retry-non-retryable.sh
|
|
467
|
+
echo "Testing non-retryable error..."
|
|
468
|
+
|
|
469
|
+
# Errores que NO deben reintentarse
|
|
470
|
+
NON_RETRYABLE_ERRORS=(
|
|
471
|
+
"AUTHENTICATION_FAILED"
|
|
472
|
+
"INVALID_INPUT"
|
|
473
|
+
"PERMISSION_DENIED"
|
|
474
|
+
"RESOURCE_NOT_FOUND"
|
|
475
|
+
)
|
|
476
|
+
|
|
477
|
+
simulate_non_retryable() {
|
|
478
|
+
local error_type=$1
|
|
479
|
+
echo "[INFO] Error type: $error_type"
|
|
480
|
+
|
|
481
|
+
for non_retry in "${NON_RETRYABLE_ERRORS[@]}"; do
|
|
482
|
+
if [ "$error_type" == "$non_retry" ]; then
|
|
483
|
+
echo "[PASS] Error '$error_type' correctly marked as non-retryable"
|
|
484
|
+
echo "[INFO] No retry attempt should be made"
|
|
485
|
+
return 0
|
|
486
|
+
fi
|
|
487
|
+
done
|
|
488
|
+
|
|
489
|
+
echo "[INFO] Error '$error_type' is retryable"
|
|
490
|
+
return 1
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
simulate_non_retryable "AUTHENTICATION_FAILED"
|
|
494
|
+
simulate_non_retryable "NETWORK_TIMEOUT" # Este SI es retryable
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
---
|
|
498
|
+
|
|
499
|
+
## Contrato 5: Error Aggregation Tests
|
|
500
|
+
|
|
501
|
+
### Test 5.1: Quorum Met (Happy Path)
|
|
502
|
+
|
|
503
|
+
**Escenario Manual:**
|
|
504
|
+
1. Wave con 3 agentes paralelos
|
|
505
|
+
2. 2 agentes exitosos, 1 falla
|
|
506
|
+
3. Policy: quorum (50%)
|
|
507
|
+
4. Esperar: Wave continua (66% > 50%)
|
|
508
|
+
|
|
509
|
+
**Script Automatizado:**
|
|
510
|
+
```bash
|
|
511
|
+
#!/bin/bash
|
|
512
|
+
# test-aggregator-quorum-met.sh
|
|
513
|
+
echo "Testing quorum met scenario..."
|
|
514
|
+
|
|
515
|
+
TOTAL_AGENTS=3
|
|
516
|
+
SUCCESSFUL=2
|
|
517
|
+
FAILED=1
|
|
518
|
+
QUORUM_THRESHOLD=50
|
|
519
|
+
|
|
520
|
+
success_rate=$((SUCCESSFUL * 100 / TOTAL_AGENTS))
|
|
521
|
+
|
|
522
|
+
echo "[INFO] Total agents: $TOTAL_AGENTS"
|
|
523
|
+
echo "[INFO] Successful: $SUCCESSFUL"
|
|
524
|
+
echo "[INFO] Failed: $FAILED"
|
|
525
|
+
echo "[INFO] Success rate: ${success_rate}%"
|
|
526
|
+
echo "[INFO] Quorum threshold: ${QUORUM_THRESHOLD}%"
|
|
527
|
+
|
|
528
|
+
if [ $success_rate -ge $QUORUM_THRESHOLD ]; then
|
|
529
|
+
echo ""
|
|
530
|
+
echo "[PASS] Quorum met (${success_rate}% >= ${QUORUM_THRESHOLD}%)"
|
|
531
|
+
echo "[INFO] Wave continues despite $FAILED failure(s)"
|
|
532
|
+
else
|
|
533
|
+
echo ""
|
|
534
|
+
echo "[FAIL] Quorum not met"
|
|
535
|
+
fi
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
### Test 5.2: Quorum Not Met (Error Path)
|
|
539
|
+
|
|
540
|
+
**Escenario Manual:**
|
|
541
|
+
1. Wave con 3 agentes paralelos
|
|
542
|
+
2. 1 agente exitoso, 2 fallan
|
|
543
|
+
3. Policy: quorum (50%)
|
|
544
|
+
4. Esperar: Wave falla (33% < 50%)
|
|
545
|
+
|
|
546
|
+
**Script Automatizado:**
|
|
547
|
+
```bash
|
|
548
|
+
#!/bin/bash
|
|
549
|
+
# test-aggregator-quorum-not-met.sh
|
|
550
|
+
echo "Testing quorum not met scenario..."
|
|
551
|
+
|
|
552
|
+
TOTAL_AGENTS=3
|
|
553
|
+
SUCCESSFUL=1
|
|
554
|
+
FAILED=2
|
|
555
|
+
QUORUM_THRESHOLD=50
|
|
556
|
+
|
|
557
|
+
success_rate=$((SUCCESSFUL * 100 / TOTAL_AGENTS))
|
|
558
|
+
|
|
559
|
+
echo "[INFO] Total agents: $TOTAL_AGENTS"
|
|
560
|
+
echo "[INFO] Successful: $SUCCESSFUL"
|
|
561
|
+
echo "[INFO] Failed: $FAILED"
|
|
562
|
+
echo "[INFO] Success rate: ${success_rate}%"
|
|
563
|
+
echo "[INFO] Quorum threshold: ${QUORUM_THRESHOLD}%"
|
|
564
|
+
|
|
565
|
+
if [ $success_rate -ge $QUORUM_THRESHOLD ]; then
|
|
566
|
+
echo ""
|
|
567
|
+
echo "[FAIL] Quorum unexpectedly met"
|
|
568
|
+
else
|
|
569
|
+
echo ""
|
|
570
|
+
echo "[PASS] Quorum correctly not met (${success_rate}% < ${QUORUM_THRESHOLD}%)"
|
|
571
|
+
echo "[EXPECTED] System should emit: Error HIGH 'Quorum not met'"
|
|
572
|
+
fi
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
### Test 5.3: Fail Fast (Edge Case)
|
|
576
|
+
|
|
577
|
+
**Escenario Manual:**
|
|
578
|
+
1. Wave con 3 agentes paralelos
|
|
579
|
+
2. Policy: fail_fast
|
|
580
|
+
3. Primer agente falla
|
|
581
|
+
4. Esperar: Wave cancela inmediatamente, otros agentes terminados
|
|
582
|
+
|
|
583
|
+
**Script Automatizado:**
|
|
584
|
+
```bash
|
|
585
|
+
#!/bin/bash
|
|
586
|
+
# test-aggregator-fail-fast.sh
|
|
587
|
+
echo "Testing fail-fast policy..."
|
|
588
|
+
|
|
589
|
+
POLICY="fail_fast"
|
|
590
|
+
|
|
591
|
+
cat << 'EOF'
|
|
592
|
+
Scenario:
|
|
593
|
+
Agent-1: starts, fails at t=5s
|
|
594
|
+
Agent-2: starts, would complete at t=10s
|
|
595
|
+
Agent-3: starts, would complete at t=15s
|
|
596
|
+
|
|
597
|
+
With fail_fast policy:
|
|
598
|
+
t=5s: Agent-1 fails
|
|
599
|
+
t=5s: Wave immediately cancelled
|
|
600
|
+
t=5s: Agent-2 and Agent-3 terminated
|
|
601
|
+
|
|
602
|
+
Expected behavior:
|
|
603
|
+
- No wait for other agents
|
|
604
|
+
- Immediate error propagation
|
|
605
|
+
- Cleanup of running agents
|
|
606
|
+
EOF
|
|
607
|
+
|
|
608
|
+
echo ""
|
|
609
|
+
echo "[PASS] Fail-fast policy documented and understood"
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
---
|
|
613
|
+
|
|
614
|
+
## Contrato 6: Severity Classification Tests
|
|
615
|
+
|
|
616
|
+
### Test 6.1: Error CRITICAL
|
|
617
|
+
|
|
618
|
+
**Escenario Manual:**
|
|
619
|
+
1. Simular error de sistema (session corrupta)
|
|
620
|
+
2. Verificar clasificacion como CRITICAL
|
|
621
|
+
3. Esperar: Ejecucion detenida, alerta enviada
|
|
622
|
+
|
|
623
|
+
**Script Automatizado:**
|
|
624
|
+
```bash
|
|
625
|
+
#!/bin/bash
|
|
626
|
+
# test-severity-critical.sh
|
|
627
|
+
echo "Testing CRITICAL severity classification..."
|
|
628
|
+
|
|
629
|
+
# Errores que deben ser CRITICAL
|
|
630
|
+
CRITICAL_ERRORS=(
|
|
631
|
+
"SESSION_CORRUPTED"
|
|
632
|
+
"DATA_INTEGRITY_VIOLATION"
|
|
633
|
+
"SYSTEM_FAILURE"
|
|
634
|
+
"SECURITY_BREACH"
|
|
635
|
+
)
|
|
636
|
+
|
|
637
|
+
classify_severity() {
|
|
638
|
+
local error=$1
|
|
639
|
+
|
|
640
|
+
for critical in "${CRITICAL_ERRORS[@]}"; do
|
|
641
|
+
if [ "$error" == "$critical" ]; then
|
|
642
|
+
echo "CRITICAL"
|
|
643
|
+
return 0
|
|
644
|
+
fi
|
|
645
|
+
done
|
|
646
|
+
|
|
647
|
+
echo "NOT_CRITICAL"
|
|
648
|
+
return 1
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
for error in "${CRITICAL_ERRORS[@]}"; do
|
|
652
|
+
result=$(classify_severity "$error")
|
|
653
|
+
if [ "$result" == "CRITICAL" ]; then
|
|
654
|
+
echo "[PASS] '$error' correctly classified as CRITICAL"
|
|
655
|
+
else
|
|
656
|
+
echo "[FAIL] '$error' should be CRITICAL"
|
|
657
|
+
fi
|
|
658
|
+
done
|
|
659
|
+
```
|
|
660
|
+
|
|
661
|
+
### Test 6.2: Error HIGH
|
|
662
|
+
|
|
663
|
+
**Escenario Manual:**
|
|
664
|
+
1. Simular error de operacion (timeout, retry exhausted)
|
|
665
|
+
2. Verificar clasificacion como HIGH
|
|
666
|
+
3. Esperar: Operacion falla, logged, puede continuar otras
|
|
667
|
+
|
|
668
|
+
**Script Automatizado:**
|
|
669
|
+
```bash
|
|
670
|
+
#!/bin/bash
|
|
671
|
+
# test-severity-high.sh
|
|
672
|
+
echo "Testing HIGH severity classification..."
|
|
673
|
+
|
|
674
|
+
# Errores que deben ser HIGH
|
|
675
|
+
HIGH_ERRORS=(
|
|
676
|
+
"OPERATION_TIMEOUT"
|
|
677
|
+
"MAX_RETRIES_EXCEEDED"
|
|
678
|
+
"AGENT_FAILURE"
|
|
679
|
+
"QUORUM_NOT_MET"
|
|
680
|
+
"INVALID_STATE_TRANSITION"
|
|
681
|
+
)
|
|
682
|
+
|
|
683
|
+
classify_severity() {
|
|
684
|
+
local error=$1
|
|
685
|
+
|
|
686
|
+
for high in "${HIGH_ERRORS[@]}"; do
|
|
687
|
+
if [ "$error" == "$high" ]; then
|
|
688
|
+
echo "HIGH"
|
|
689
|
+
return 0
|
|
690
|
+
fi
|
|
691
|
+
done
|
|
692
|
+
|
|
693
|
+
echo "NOT_HIGH"
|
|
694
|
+
return 1
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
for error in "${HIGH_ERRORS[@]}"; do
|
|
698
|
+
result=$(classify_severity "$error")
|
|
699
|
+
if [ "$result" == "HIGH" ]; then
|
|
700
|
+
echo "[PASS] '$error' correctly classified as HIGH"
|
|
701
|
+
else
|
|
702
|
+
echo "[FAIL] '$error' should be HIGH"
|
|
703
|
+
fi
|
|
704
|
+
done
|
|
705
|
+
```
|
|
706
|
+
|
|
707
|
+
### Test 6.3: Warning MEDIUM
|
|
708
|
+
|
|
709
|
+
**Escenario Manual:**
|
|
710
|
+
1. Simular warning (retry en progreso, performance degradada)
|
|
711
|
+
2. Verificar clasificacion como MEDIUM
|
|
712
|
+
3. Esperar: Logged, operacion continua
|
|
713
|
+
|
|
714
|
+
**Script Automatizado:**
|
|
715
|
+
```bash
|
|
716
|
+
#!/bin/bash
|
|
717
|
+
# test-severity-medium.sh
|
|
718
|
+
echo "Testing MEDIUM severity classification..."
|
|
719
|
+
|
|
720
|
+
# Warnings que deben ser MEDIUM
|
|
721
|
+
MEDIUM_WARNINGS=(
|
|
722
|
+
"RETRY_IN_PROGRESS"
|
|
723
|
+
"PERFORMANCE_DEGRADED"
|
|
724
|
+
"CACHE_MISS"
|
|
725
|
+
"FALLBACK_ACTIVATED"
|
|
726
|
+
"DEPENDENCY_SLOW"
|
|
727
|
+
)
|
|
728
|
+
|
|
729
|
+
classify_severity() {
|
|
730
|
+
local warning=$1
|
|
731
|
+
|
|
732
|
+
for medium in "${MEDIUM_WARNINGS[@]}"; do
|
|
733
|
+
if [ "$warning" == "$medium" ]; then
|
|
734
|
+
echo "MEDIUM"
|
|
735
|
+
return 0
|
|
736
|
+
fi
|
|
737
|
+
done
|
|
738
|
+
|
|
739
|
+
echo "NOT_MEDIUM"
|
|
740
|
+
return 1
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
for warning in "${MEDIUM_WARNINGS[@]}"; do
|
|
744
|
+
result=$(classify_severity "$warning")
|
|
745
|
+
if [ "$result" == "MEDIUM" ]; then
|
|
746
|
+
echo "[PASS] '$warning' correctly classified as MEDIUM"
|
|
747
|
+
else
|
|
748
|
+
echo "[FAIL] '$warning' should be MEDIUM"
|
|
749
|
+
fi
|
|
750
|
+
done
|
|
751
|
+
```
|
|
752
|
+
|
|
753
|
+
---
|
|
754
|
+
|
|
755
|
+
## Contrato 7: Session Validation Tests
|
|
756
|
+
|
|
757
|
+
### Test 7.1: Session Valida (Happy Path)
|
|
758
|
+
|
|
759
|
+
**Escenario Manual:**
|
|
760
|
+
1. Iniciar session con `/elsabro:init`
|
|
761
|
+
2. Verificar `.claude/elsabro-session.json` creado
|
|
762
|
+
3. Ejecutar comando subsecuente
|
|
763
|
+
4. Esperar: Session validada, operacion procede
|
|
764
|
+
|
|
765
|
+
**Script Automatizado:**
|
|
766
|
+
```bash
|
|
767
|
+
#!/bin/bash
|
|
768
|
+
# test-session-valid.sh
|
|
769
|
+
echo "Testing valid session..."
|
|
770
|
+
|
|
771
|
+
SESSION_FILE=".claude/elsabro-session.json"
|
|
772
|
+
|
|
773
|
+
# Verificar existencia
|
|
774
|
+
if [ ! -f "$SESSION_FILE" ]; then
|
|
775
|
+
echo "[SKIP] No session file found - run /elsabro:init first"
|
|
776
|
+
exit 0
|
|
777
|
+
fi
|
|
778
|
+
|
|
779
|
+
# Verificar JSON valido
|
|
780
|
+
if jq empty "$SESSION_FILE" 2>/dev/null; then
|
|
781
|
+
echo "[PASS] Session file is valid JSON"
|
|
782
|
+
else
|
|
783
|
+
echo "[FAIL] Session file is not valid JSON"
|
|
784
|
+
exit 1
|
|
785
|
+
fi
|
|
786
|
+
|
|
787
|
+
# Verificar campos requeridos
|
|
788
|
+
required_fields=("session_id" "started_at" "status")
|
|
789
|
+
for field in "${required_fields[@]}"; do
|
|
790
|
+
if jq -e ".$field" "$SESSION_FILE" > /dev/null 2>&1; then
|
|
791
|
+
echo "[PASS] Required field '$field' present"
|
|
792
|
+
else
|
|
793
|
+
echo "[FAIL] Required field '$field' missing"
|
|
794
|
+
fi
|
|
795
|
+
done
|
|
796
|
+
```
|
|
797
|
+
|
|
798
|
+
### Test 7.2: Session Corrupta (Error Path)
|
|
799
|
+
|
|
800
|
+
**Escenario Manual:**
|
|
801
|
+
1. Modificar `.claude/elsabro-session.json` con JSON invalido
|
|
802
|
+
2. Ejecutar cualquier comando ELSABRO
|
|
803
|
+
3. Esperar: Error CRITICAL "Session corrupted"
|
|
804
|
+
4. Restaurar session
|
|
805
|
+
|
|
806
|
+
**Script Automatizado:**
|
|
807
|
+
```bash
|
|
808
|
+
#!/bin/bash
|
|
809
|
+
# test-session-corrupt.sh
|
|
810
|
+
echo "Testing corrupt session handling..."
|
|
811
|
+
|
|
812
|
+
SESSION_FILE=".claude/elsabro-session.json"
|
|
813
|
+
BACKUP_FILE=".claude/elsabro-session.json.bak"
|
|
814
|
+
|
|
815
|
+
# Backup si existe
|
|
816
|
+
if [ -f "$SESSION_FILE" ]; then
|
|
817
|
+
cp "$SESSION_FILE" "$BACKUP_FILE"
|
|
818
|
+
echo "[INFO] Session backed up"
|
|
819
|
+
fi
|
|
820
|
+
|
|
821
|
+
# Crear session corrupta
|
|
822
|
+
echo "{ invalid json here" > "$SESSION_FILE"
|
|
823
|
+
echo "[INFO] Corrupt session created"
|
|
824
|
+
|
|
825
|
+
# Verificar que es invalido
|
|
826
|
+
if jq empty "$SESSION_FILE" 2>/dev/null; then
|
|
827
|
+
echo "[FAIL] Session should be invalid JSON"
|
|
828
|
+
else
|
|
829
|
+
echo "[PASS] Session correctly detected as corrupt"
|
|
830
|
+
fi
|
|
831
|
+
|
|
832
|
+
# Restaurar
|
|
833
|
+
if [ -f "$BACKUP_FILE" ]; then
|
|
834
|
+
mv "$BACKUP_FILE" "$SESSION_FILE"
|
|
835
|
+
echo "[INFO] Session restored"
|
|
836
|
+
fi
|
|
837
|
+
```
|
|
838
|
+
|
|
839
|
+
### Test 7.3: Session Stale (Edge Case)
|
|
840
|
+
|
|
841
|
+
**Escenario Manual:**
|
|
842
|
+
1. Session con `started_at` de hace 24+ horas
|
|
843
|
+
2. Ejecutar comando
|
|
844
|
+
3. Esperar: Warning MEDIUM "Session stale", sugerencia de refresh
|
|
845
|
+
|
|
846
|
+
**Script Automatizado:**
|
|
847
|
+
```bash
|
|
848
|
+
#!/bin/bash
|
|
849
|
+
# test-session-stale.sh
|
|
850
|
+
echo "Testing stale session detection..."
|
|
851
|
+
|
|
852
|
+
SESSION_FILE=".claude/elsabro-session.json"
|
|
853
|
+
STALE_THRESHOLD_HOURS=24
|
|
854
|
+
|
|
855
|
+
# Verificar session
|
|
856
|
+
if [ ! -f "$SESSION_FILE" ]; then
|
|
857
|
+
echo "[SKIP] No session file"
|
|
858
|
+
exit 0
|
|
859
|
+
fi
|
|
860
|
+
|
|
861
|
+
# Obtener timestamp
|
|
862
|
+
started_at=$(jq -r '.started_at' "$SESSION_FILE" 2>/dev/null)
|
|
863
|
+
if [ -z "$started_at" ] || [ "$started_at" == "null" ]; then
|
|
864
|
+
echo "[FAIL] No started_at field"
|
|
865
|
+
exit 1
|
|
866
|
+
fi
|
|
867
|
+
|
|
868
|
+
# Calcular edad (simplificado)
|
|
869
|
+
echo "[INFO] Session started at: $started_at"
|
|
870
|
+
echo "[INFO] Stale threshold: ${STALE_THRESHOLD_HOURS} hours"
|
|
871
|
+
|
|
872
|
+
# En implementacion real, calcular diferencia de timestamps
|
|
873
|
+
echo "[PASS] Stale detection logic documented"
|
|
874
|
+
```
|
|
875
|
+
|
|
876
|
+
---
|
|
877
|
+
|
|
878
|
+
## Tests de Integracion
|
|
879
|
+
|
|
880
|
+
### Integration Test 1: Ejecucion Paralela Completa
|
|
881
|
+
|
|
882
|
+
**Escenario:**
|
|
883
|
+
- Wave con 3 agentes ejecutando en paralelo
|
|
884
|
+
- 1 agente falla despues de 5 segundos
|
|
885
|
+
- Policy: quorum (50%)
|
|
886
|
+
|
|
887
|
+
**Esperado:**
|
|
888
|
+
- Wave continua (2/3 = 66% > 50%)
|
|
889
|
+
- Error del agente fallido logged
|
|
890
|
+
- Resultados de agentes exitosos agregados
|
|
891
|
+
|
|
892
|
+
**Script:**
|
|
893
|
+
```bash
|
|
894
|
+
#!/bin/bash
|
|
895
|
+
# test-integration-parallel.sh
|
|
896
|
+
echo "Integration Test: Parallel Execution with Quorum"
|
|
897
|
+
echo "================================================"
|
|
898
|
+
|
|
899
|
+
simulate_wave() {
|
|
900
|
+
echo "[t=0s] Wave started with 3 agents"
|
|
901
|
+
echo "[t=0s] Agent-1: Starting..."
|
|
902
|
+
echo "[t=0s] Agent-2: Starting..."
|
|
903
|
+
echo "[t=0s] Agent-3: Starting..."
|
|
904
|
+
sleep 1
|
|
905
|
+
echo "[t=5s] Agent-1: FAILED (simulated error)"
|
|
906
|
+
echo "[t=5s] Aggregator: 1 failure detected, checking quorum..."
|
|
907
|
+
sleep 1
|
|
908
|
+
echo "[t=10s] Agent-2: Completed successfully"
|
|
909
|
+
echo "[t=10s] Agent-3: Completed successfully"
|
|
910
|
+
echo "[t=10s] Aggregator: 2/3 succeeded (66%)"
|
|
911
|
+
echo "[t=10s] Aggregator: Quorum met (66% >= 50%)"
|
|
912
|
+
echo ""
|
|
913
|
+
echo "[RESULT] Wave completed with partial success"
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
simulate_wave
|
|
917
|
+
```
|
|
918
|
+
|
|
919
|
+
### Integration Test 2: Cascada de Errores
|
|
920
|
+
|
|
921
|
+
**Escenario:**
|
|
922
|
+
- Session corrupta detectada
|
|
923
|
+
- Intento de ejecutar wave
|
|
924
|
+
- Agente faltante (no se llega a detectar)
|
|
925
|
+
|
|
926
|
+
**Esperado:**
|
|
927
|
+
- Error CRITICAL de session PRIMERO
|
|
928
|
+
- Wave nunca inicia
|
|
929
|
+
- Agente faltante no relevante
|
|
930
|
+
|
|
931
|
+
**Script:**
|
|
932
|
+
```bash
|
|
933
|
+
#!/bin/bash
|
|
934
|
+
# test-integration-cascade.sh
|
|
935
|
+
echo "Integration Test: Error Cascade Priority"
|
|
936
|
+
echo "========================================="
|
|
937
|
+
|
|
938
|
+
simulate_cascade() {
|
|
939
|
+
echo "[Step 1] Checking session..."
|
|
940
|
+
echo "[Step 1] ERROR: Session corrupted"
|
|
941
|
+
echo "[Step 1] Severity: CRITICAL"
|
|
942
|
+
echo ""
|
|
943
|
+
echo "[Step 2] Wave initialization..."
|
|
944
|
+
echo "[Step 2] BLOCKED: Cannot proceed with corrupted session"
|
|
945
|
+
echo ""
|
|
946
|
+
echo "[Note] Agent registry check never executed"
|
|
947
|
+
echo "[Note] Registry errors would be detected if session was valid"
|
|
948
|
+
echo ""
|
|
949
|
+
echo "[RESULT] CRITICAL errors halt before lower-priority checks"
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
simulate_cascade
|
|
953
|
+
```
|
|
954
|
+
|
|
955
|
+
### Integration Test 3: Recovery Path
|
|
956
|
+
|
|
957
|
+
**Escenario:**
|
|
958
|
+
- Operacion falla en primer intento
|
|
959
|
+
- Retry automatico activado
|
|
960
|
+
- Segundo intento exitoso
|
|
961
|
+
|
|
962
|
+
**Esperado:**
|
|
963
|
+
- Error inicial logged
|
|
964
|
+
- Retry con backoff
|
|
965
|
+
- Operacion completada exitosamente
|
|
966
|
+
- Log de recovery
|
|
967
|
+
|
|
968
|
+
**Script:**
|
|
969
|
+
```bash
|
|
970
|
+
#!/bin/bash
|
|
971
|
+
# test-integration-recovery.sh
|
|
972
|
+
echo "Integration Test: Error Recovery Path"
|
|
973
|
+
echo "======================================"
|
|
974
|
+
|
|
975
|
+
simulate_recovery() {
|
|
976
|
+
echo "[t=0s] Operation started"
|
|
977
|
+
echo "[t=5s] Operation FAILED: NETWORK_TIMEOUT"
|
|
978
|
+
echo "[t=5s] Retry policy: 3 attempts, 2s backoff"
|
|
979
|
+
echo "[t=5s] Scheduling retry #1..."
|
|
980
|
+
sleep 1
|
|
981
|
+
echo "[t=7s] Retry #1 started"
|
|
982
|
+
echo "[t=10s] Retry #1 SUCCEEDED"
|
|
983
|
+
echo ""
|
|
984
|
+
echo "[Summary]"
|
|
985
|
+
echo " Initial attempt: FAILED"
|
|
986
|
+
echo " Retry attempts: 1"
|
|
987
|
+
echo " Final status: SUCCESS"
|
|
988
|
+
echo " Total time: 10s"
|
|
989
|
+
echo ""
|
|
990
|
+
echo "[RESULT] Operation recovered via retry mechanism"
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
simulate_recovery
|
|
994
|
+
```
|
|
995
|
+
|
|
996
|
+
### Integration Test 4: Full Error Chain
|
|
997
|
+
|
|
998
|
+
**Escenario:**
|
|
999
|
+
- Session valida
|
|
1000
|
+
- Wave inicia
|
|
1001
|
+
- Timeout en agente
|
|
1002
|
+
- Retry falla
|
|
1003
|
+
- Quorum no alcanzado
|
|
1004
|
+
- Error propagado
|
|
1005
|
+
|
|
1006
|
+
**Script:**
|
|
1007
|
+
```bash
|
|
1008
|
+
#!/bin/bash
|
|
1009
|
+
# test-integration-full-chain.sh
|
|
1010
|
+
echo "Integration Test: Full Error Chain"
|
|
1011
|
+
echo "==================================="
|
|
1012
|
+
|
|
1013
|
+
cat << 'EOF'
|
|
1014
|
+
Timeline:
|
|
1015
|
+
[t=0s] Session validated: OK
|
|
1016
|
+
[t=0s] Wave started: 3 agents
|
|
1017
|
+
[t=30s] Agent-1: TIMEOUT
|
|
1018
|
+
[t=32s] Agent-1: Retry #1 started
|
|
1019
|
+
[t=62s] Agent-1: Retry #1 TIMEOUT
|
|
1020
|
+
[t=64s] Agent-1: Retry #2 started
|
|
1021
|
+
[t=94s] Agent-1: Retry #2 TIMEOUT
|
|
1022
|
+
[t=94s] Agent-1: MAX_RETRIES_EXCEEDED
|
|
1023
|
+
[t=94s] Agent-2: TIMEOUT (while Agent-1 retrying)
|
|
1024
|
+
[t=96s] Agent-2: Retry #1 started
|
|
1025
|
+
[t=100s] Agent-3: Completed OK
|
|
1026
|
+
[t=126s] Agent-2: Retry #1 TIMEOUT
|
|
1027
|
+
[t=126s] Agent-2: Retry #2 started
|
|
1028
|
+
[t=156s] Agent-2: MAX_RETRIES_EXCEEDED
|
|
1029
|
+
|
|
1030
|
+
Aggregation:
|
|
1031
|
+
Successful: 1/3 (33%)
|
|
1032
|
+
Failed: 2/3 (Agent-1, Agent-2)
|
|
1033
|
+
Quorum threshold: 50%
|
|
1034
|
+
Quorum met: NO
|
|
1035
|
+
|
|
1036
|
+
Result:
|
|
1037
|
+
Error: HIGH - Quorum not met
|
|
1038
|
+
Wave: FAILED
|
|
1039
|
+
|
|
1040
|
+
Contracts Exercised:
|
|
1041
|
+
1. Session Validation: PASS
|
|
1042
|
+
2. Task Lifecycle: Multiple transitions
|
|
1043
|
+
3. Timeout Handler: 6 timeouts handled
|
|
1044
|
+
4. Retry Policy: 4 retries attempted
|
|
1045
|
+
5. Error Aggregator: Quorum calculation
|
|
1046
|
+
6. Severity Classification: HIGH assigned
|
|
1047
|
+
7. Registry: Agents found (not exercised in failure)
|
|
1048
|
+
EOF
|
|
1049
|
+
```
|
|
1050
|
+
|
|
1051
|
+
---
|
|
1052
|
+
|
|
1053
|
+
## Matriz de Cobertura
|
|
1054
|
+
|
|
1055
|
+
| Contrato | Happy Path | Error Path | Edge Cases | Total |
|
|
1056
|
+
|----------|------------|------------|------------|-------|
|
|
1057
|
+
| Registry | Test 1.1 | Test 1.2 | Test 1.3 | 3/3 |
|
|
1058
|
+
| Lifecycle | Test 2.1 | Test 2.2 | Test 2.3 | 3/3 |
|
|
1059
|
+
| Timeout | Test 3.1 | Test 3.3 | Test 3.2 | 3/3 |
|
|
1060
|
+
| Retry | Test 4.1 | Test 4.2 | Test 4.3 | 3/3 |
|
|
1061
|
+
| Aggregator | Test 5.1 | Test 5.2 | Test 5.3 | 3/3 |
|
|
1062
|
+
| Severity | Test 6.1 | Test 6.2 | Test 6.3 | 3/3 |
|
|
1063
|
+
| Session | Test 7.1 | Test 7.2 | Test 7.3 | 3/3 |
|
|
1064
|
+
| **Total** | **7/7** | **7/7** | **7/7** | **21/21** |
|
|
1065
|
+
|
|
1066
|
+
## Integracion Tests
|
|
1067
|
+
|
|
1068
|
+
| Test | Contratos Cubiertos | Resultado Esperado |
|
|
1069
|
+
|------|--------------------|--------------------|
|
|
1070
|
+
| Parallel Execution | 2, 5, 6 | Wave completa con quorum |
|
|
1071
|
+
| Error Cascade | 1, 6, 7 | CRITICAL bloquea todo |
|
|
1072
|
+
| Recovery Path | 3, 4, 6 | Exito despues de retry |
|
|
1073
|
+
| Full Chain | 1-7 | Todos ejercitados |
|
|
1074
|
+
|
|
1075
|
+
---
|
|
1076
|
+
|
|
1077
|
+
## Guia de Ejecucion
|
|
1078
|
+
|
|
1079
|
+
### Ejecutar Todos los Tests
|
|
1080
|
+
|
|
1081
|
+
```bash
|
|
1082
|
+
#!/bin/bash
|
|
1083
|
+
# run-all-tests.sh
|
|
1084
|
+
|
|
1085
|
+
echo "ELSABRO Error Contracts Test Suite"
|
|
1086
|
+
echo "==================================="
|
|
1087
|
+
echo ""
|
|
1088
|
+
|
|
1089
|
+
TEST_DIR="tests/contracts"
|
|
1090
|
+
RESULTS=()
|
|
1091
|
+
|
|
1092
|
+
for test_file in "$TEST_DIR"/*.sh; do
|
|
1093
|
+
echo "Running: $test_file"
|
|
1094
|
+
if bash "$test_file"; then
|
|
1095
|
+
RESULTS+=("[PASS] $test_file")
|
|
1096
|
+
else
|
|
1097
|
+
RESULTS+=("[FAIL] $test_file")
|
|
1098
|
+
fi
|
|
1099
|
+
echo ""
|
|
1100
|
+
done
|
|
1101
|
+
|
|
1102
|
+
echo "==================================="
|
|
1103
|
+
echo "Summary:"
|
|
1104
|
+
for result in "${RESULTS[@]}"; do
|
|
1105
|
+
echo " $result"
|
|
1106
|
+
done
|
|
1107
|
+
```
|
|
1108
|
+
|
|
1109
|
+
### Ejecutar Tests por Contrato
|
|
1110
|
+
|
|
1111
|
+
```bash
|
|
1112
|
+
# Solo tests de Registry
|
|
1113
|
+
bash tests/contracts/test-registry-*.sh
|
|
1114
|
+
|
|
1115
|
+
# Solo tests de Timeout
|
|
1116
|
+
bash tests/contracts/test-timeout-*.sh
|
|
1117
|
+
|
|
1118
|
+
# Solo tests de Integracion
|
|
1119
|
+
bash tests/contracts/test-integration-*.sh
|
|
1120
|
+
```
|
|
1121
|
+
|
|
1122
|
+
### CI/CD Integration
|
|
1123
|
+
|
|
1124
|
+
```yaml
|
|
1125
|
+
# .github/workflows/test-contracts.yml
|
|
1126
|
+
name: Error Contracts Tests
|
|
1127
|
+
|
|
1128
|
+
on: [push, pull_request]
|
|
1129
|
+
|
|
1130
|
+
jobs:
|
|
1131
|
+
test:
|
|
1132
|
+
runs-on: ubuntu-latest
|
|
1133
|
+
steps:
|
|
1134
|
+
- uses: actions/checkout@v3
|
|
1135
|
+
|
|
1136
|
+
- name: Run Contract Tests
|
|
1137
|
+
run: |
|
|
1138
|
+
chmod +x tests/contracts/*.sh
|
|
1139
|
+
bash run-all-tests.sh
|
|
1140
|
+
|
|
1141
|
+
- name: Upload Results
|
|
1142
|
+
if: always()
|
|
1143
|
+
uses: actions/upload-artifact@v3
|
|
1144
|
+
with:
|
|
1145
|
+
name: test-results
|
|
1146
|
+
path: test-results/
|
|
1147
|
+
```
|
|
1148
|
+
|
|
1149
|
+
---
|
|
1150
|
+
|
|
1151
|
+
## Notas de Mantenimiento
|
|
1152
|
+
|
|
1153
|
+
### Cuando Agregar Tests
|
|
1154
|
+
|
|
1155
|
+
1. **Nuevo contrato**: Agregar seccion completa (happy, error, edge)
|
|
1156
|
+
2. **Nuevo error type**: Agregar a test de severity apropiado
|
|
1157
|
+
3. **Nueva policy**: Agregar test en aggregator section
|
|
1158
|
+
|
|
1159
|
+
### Cuando Actualizar Tests
|
|
1160
|
+
|
|
1161
|
+
1. **Cambio en threshold**: Actualizar valores en scripts
|
|
1162
|
+
2. **Nuevo estado en lifecycle**: Actualizar transiciones validas
|
|
1163
|
+
3. **Cambio en retry policy**: Actualizar MAX_RETRIES y delays
|
|
1164
|
+
|
|
1165
|
+
### Review Checklist
|
|
1166
|
+
|
|
1167
|
+
- [ ] Todos los contratos tienen 3 tests minimo
|
|
1168
|
+
- [ ] Scripts son ejecutables standalone
|
|
1169
|
+
- [ ] Cleanup apropiado (restaurar backups)
|
|
1170
|
+
- [ ] Exit codes correctos (0=pass, 1=fail)
|
|
1171
|
+
- [ ] Logs claros y parseables
|