elsabro 7.1.0 → 7.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/commands/elsabro/execute.md +94 -1479
- package/flow-engine/src/executors.js +1 -1
- package/flow-engine/tests/skill-install.test.js +374 -0
- package/flows/development-flow.json +20 -20
- package/hooks/skill-discovery.sh +6 -4
- package/hooks/skill-install.sh +224 -0
- package/package.json +1 -1
- package/references/SYSTEM_INDEX.md +1 -1
- package/references/agent-teams-integration.md +7 -15
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: execute
|
|
3
|
-
description: Ejecutar un plan
|
|
3
|
+
description: Ejecutar un plan via CLI flow engine con observabilidad
|
|
4
4
|
allowed-tools:
|
|
5
5
|
- Read
|
|
6
6
|
- Write
|
|
@@ -9,1558 +9,173 @@ allowed-tools:
|
|
|
9
9
|
- Glob
|
|
10
10
|
- Grep
|
|
11
11
|
- Task
|
|
12
|
-
- TaskCreate
|
|
13
|
-
- TaskUpdate
|
|
14
|
-
- TaskList
|
|
15
|
-
- TaskGet
|
|
16
12
|
- TeamCreate
|
|
17
13
|
- TeamDelete
|
|
18
14
|
- SendMessage
|
|
19
15
|
- AskUserQuestion
|
|
20
|
-
|
|
21
|
-
argument-hint: "[número de fase]"
|
|
16
|
+
argument-hint: "[numero de fase]"
|
|
22
17
|
sync:
|
|
23
18
|
reads: [".elsabro/state.json", ".planning/*-PLAN.md"]
|
|
24
|
-
writes: [".elsabro/state.json", ".elsabro/context.md"]
|
|
25
|
-
phases: ["initializing", "
|
|
19
|
+
writes: [".elsabro/state.json", ".elsabro/context.md", ".elsabro/telemetry/"]
|
|
20
|
+
phases: ["initializing", "stepping", "done"]
|
|
26
21
|
passes_context_to: ["verify-work"]
|
|
27
|
-
dispatcher:
|
|
28
|
-
exploration:
|
|
29
|
-
agents: [Explore, feature-dev:code-explorer, Plan]
|
|
30
|
-
model: haiku
|
|
31
|
-
parallel: true
|
|
32
|
-
min_agents: 3
|
|
33
|
-
method: "subagent"
|
|
34
|
-
implementation:
|
|
35
|
-
agents: [elsabro-executor, feature-dev:code-architect]
|
|
36
|
-
model: opus
|
|
37
|
-
parallel: true
|
|
38
|
-
min_agents: 2
|
|
39
|
-
method: "agent-team"
|
|
40
|
-
agent_team_config:
|
|
41
|
-
team_members: [elsabro-executor, elsabro-qa, elsabro-planner]
|
|
42
|
-
when: "always" # v4.2.0: Agent Teams obligatorio para 2+ agentes (Rule 8)
|
|
43
|
-
verification:
|
|
44
|
-
agents: [pr-review-toolkit:code-reviewer, pr-review-toolkit:silent-failure-hunter, pr-review-toolkit:pr-test-analyzer]
|
|
45
|
-
model: opus
|
|
46
|
-
parallel: true
|
|
47
|
-
min_agents: 3
|
|
48
|
-
method: "agent-team"
|
|
49
|
-
blocking: true
|
|
50
|
-
max_review_iterations: 5
|
|
51
22
|
---
|
|
52
23
|
|
|
53
24
|
# ELSABRO: Execute
|
|
54
25
|
|
|
55
|
-
|
|
56
|
-
|
|
26
|
+
Thin wrapper del CLI flow engine. Toda la logica de grafos, Agent Teams, y gates
|
|
27
|
+
vive en el engine y en `flows/development-flow.json`. Este archivo solo define el loop.
|
|
57
28
|
|
|
58
|
-
**
|
|
29
|
+
**Reglas**: @references/enforcement-rules.md
|
|
30
|
+
**State sync**: @references/state-sync.md
|
|
59
31
|
|
|
60
|
-
|
|
32
|
+
## 1. Inicializar
|
|
61
33
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
TaskCreate({
|
|
65
|
-
subject: "Initialize execute command",
|
|
66
|
-
description: "Leer estado y preparar ejecución",
|
|
67
|
-
activeForm: "Inicializando..."
|
|
68
|
-
})
|
|
69
|
-
TaskUpdate(id, status: "in_progress")
|
|
70
|
-
|
|
71
|
-
// 2. Leer estado existente
|
|
72
|
-
const state = Read(".elsabro/state.json") || createInitialState();
|
|
73
|
-
|
|
74
|
-
// 3. Verificar flujo en progreso
|
|
75
|
-
if (state.current_flow && state.current_flow.command !== "execute") {
|
|
76
|
-
AskUserQuestion({
|
|
77
|
-
questions: [{
|
|
78
|
-
question: `Hay un flujo de "${state.current_flow.command}" en progreso. ¿Continuar ese o empezar execute?`,
|
|
79
|
-
header: "Flujo",
|
|
80
|
-
options: [
|
|
81
|
-
{ label: "Continuar anterior", description: "Retomar " + state.current_flow.command },
|
|
82
|
-
{ label: "Empezar execute", description: "Pausar anterior" }
|
|
83
|
-
]
|
|
84
|
-
}]
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// 4. Actualizar estado
|
|
89
|
-
state.current_flow = { command: "execute", phase: "initializing", started_at: new Date().toISOString() };
|
|
90
|
-
state.elsabro_mode = true;
|
|
91
|
-
Write(".elsabro/state.json", JSON.stringify(state, null, 2));
|
|
92
|
-
|
|
93
|
-
// 5. Completar task de inicialización
|
|
94
|
-
TaskUpdate(id, status: "completed")
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
### Al Cambiar de Fase
|
|
98
|
-
|
|
99
|
-
```javascript
|
|
100
|
-
// Antes de exploración
|
|
101
|
-
state.current_flow.phase = "exploring";
|
|
102
|
-
Write(".elsabro/state.json", JSON.stringify(state, null, 2));
|
|
103
|
-
|
|
104
|
-
// Antes de cada wave
|
|
105
|
-
state.current_flow.phase = "executing_wave_" + waveNumber;
|
|
106
|
-
Write(".elsabro/state.json", JSON.stringify(state, null, 2));
|
|
107
|
-
|
|
108
|
-
// Antes de verificación
|
|
109
|
-
state.current_flow.phase = "verifying";
|
|
110
|
-
Write(".elsabro/state.json", JSON.stringify(state, null, 2));
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
### Al Completar
|
|
114
|
-
|
|
115
|
-
```javascript
|
|
116
|
-
// Registrar en historial
|
|
117
|
-
state.history.push({
|
|
118
|
-
command: "execute",
|
|
119
|
-
completed_at: new Date().toISOString(),
|
|
120
|
-
result: "completed_phase_" + phaseNumber,
|
|
121
|
-
artifact: null
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
// Pasar contexto a verify-work
|
|
125
|
-
state.context = state.context || {};
|
|
126
|
-
state.context.changed_files = [...changedFiles];
|
|
127
|
-
state.context.commits = [...commitIds];
|
|
128
|
-
state.context.tests_added = [...testFiles];
|
|
129
|
-
state.context.phase_completed = phaseNumber;
|
|
130
|
-
|
|
131
|
-
// Limpiar flujo y sugerir siguiente
|
|
132
|
-
state.current_flow = null;
|
|
133
|
-
state.suggested_next = "verify-work";
|
|
134
|
-
|
|
135
|
-
Write(".elsabro/state.json", JSON.stringify(state, null, 2));
|
|
136
|
-
|
|
137
|
-
// Actualizar context.md legible
|
|
138
|
-
Write(".elsabro/context.md", generateHumanReadableContext(state));
|
|
139
|
-
```
|
|
140
|
-
</state_sync>
|
|
141
|
-
|
|
142
|
-
<skill_discovery>
|
|
143
|
-
## Skill Discovery (Pre-Execution)
|
|
144
|
-
|
|
145
|
-
**ANTES de ejecutar el plan**, descubrir skills para el stack:
|
|
146
|
-
|
|
147
|
-
```javascript
|
|
148
|
-
// Ejecutar skill discovery con la tarea
|
|
149
|
-
const discoveryResult = Bash(`bash ./hooks/skill-discovery.sh "${inputs.task || state.context.current_feature || ''}" "medium"`, { timeout: 30000 });
|
|
150
|
-
|
|
151
|
-
// Guardar en estado
|
|
152
|
-
state.context = state.context || {};
|
|
153
|
-
state.context.available_skills = JSON.parse(discoveryResult).recommended || [];
|
|
154
|
-
|
|
155
|
-
// Informar al usuario
|
|
156
|
-
if (state.context.available_skills.length > 0) {
|
|
157
|
-
output(`Skills cargados: ${state.context.available_skills.map(s => s.name).join(", ")}`);
|
|
158
|
-
}
|
|
159
|
-
Write(".elsabro/state.json", JSON.stringify(state, null, 2));
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
Los skills proveen patrones de código verificados, configuraciones de setup, y guides de integración durante la implementación.
|
|
163
|
-
</skill_discovery>
|
|
164
|
-
|
|
165
|
-
<skill_injection>
|
|
166
|
-
## Skill Injection (OBLIGATORIO despues de Discovery)
|
|
167
|
-
|
|
168
|
-
**Si skill discovery encontro skills relevantes, CARGAR su contenido como contexto.**
|
|
169
|
-
|
|
170
|
-
```javascript
|
|
171
|
-
// 1. Obtener skills recomendados
|
|
172
|
-
const recommendedSkills = state.context.available_skills || [];
|
|
173
|
-
|
|
174
|
-
if (recommendedSkills.length > 0) {
|
|
175
|
-
// 2. Cargar contenido de los top-3 skills con match
|
|
176
|
-
const loadedSkills = [];
|
|
177
|
-
for (const skill of recommendedSkills.slice(0, 3)) {
|
|
178
|
-
const content = Read(`skills/${skill.id}.md`);
|
|
179
|
-
if (content) {
|
|
180
|
-
loadedSkills.push({
|
|
181
|
-
name: skill.id,
|
|
182
|
-
content: content
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// 3. Guardar skills cargados en state
|
|
188
|
-
state.context.loaded_skills = loadedSkills;
|
|
189
|
-
Write(".elsabro/state.json", JSON.stringify(state, null, 2));
|
|
190
|
-
|
|
191
|
-
// 4. Informar al usuario
|
|
192
|
-
output(`Skills cargados para esta ejecucion:`);
|
|
193
|
-
loadedSkills.forEach(s => output(` - ${s.name}`));
|
|
194
|
-
}
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
**GATE**: Cuando lances agentes executors, INCLUIR los skills en el prompt:
|
|
198
|
-
```
|
|
199
|
-
Si state.context.loaded_skills tiene contenido, agregar al prompt de CADA executor:
|
|
200
|
-
|
|
201
|
-
"SKILLS DE REFERENCIA:
|
|
202
|
-
[Para cada skill cargado:]
|
|
203
|
-
### Skill: {name}
|
|
204
|
-
{contenido del archivo .md}
|
|
205
|
-
|
|
206
|
-
Usa estos skills como guia de patrones, estructura y mejores practicas."
|
|
207
|
-
```
|
|
208
|
-
</skill_injection>
|
|
209
|
-
|
|
210
|
-
<objective>
|
|
211
|
-
Ejecutar planes de una fase con:
|
|
212
|
-
- **Sistema de Tasks para tracking real** de waves y dependencias
|
|
213
|
-
- **Dispatcher inteligente con selección automática de modelo** (ver @references/task-dispatcher.md)
|
|
214
|
-
- **Ejecución por subagentes en paralelo** según tipo de tarea
|
|
215
|
-
- Investigación de patrones con Context7
|
|
216
|
-
- TDD cuando sea apropiado
|
|
217
|
-
- Commits atómicos por tarea
|
|
218
|
-
- Verificación automática con agregador
|
|
219
|
-
</objective>
|
|
220
|
-
|
|
221
|
-
<dispatcher_integration>
|
|
222
|
-
## Selección Automática de Modelo
|
|
223
|
-
|
|
224
|
-
**REGLA CRÍTICA:** Cada tarea se ejecuta con el modelo óptimo para su tipo.
|
|
225
|
-
|
|
226
|
-
```
|
|
227
|
-
┌─────────────────────────────────────────────────────────────────────────┐
|
|
228
|
-
│ MODELO SEGÚN FASE │
|
|
229
|
-
├─────────────────────────────────────────────────────────────────────────┤
|
|
230
|
-
│ FASE │ SUBAGENTES │ MODELO │
|
|
231
|
-
├────────────────────┼────────────────────────────────────┼───────────────┤
|
|
232
|
-
│ Exploración │ Explore │ HAIKU │
|
|
233
|
-
│ (pre-ejecución) │ feature-dev:code-explorer │ HAIKU │
|
|
234
|
-
│ │ Plan │ HAIKU │
|
|
235
|
-
│ │ (3 en paralelo obligatorio) │ │
|
|
236
|
-
├────────────────────┼────────────────────────────────────┼───────────────┤
|
|
237
|
-
│ Implementación │ elsabro-executor │ OPUS │
|
|
238
|
-
│ (waves) │ feature-dev:code-architect │ OPUS │
|
|
239
|
-
│ │ (2+ en paralelo por wave) │ │
|
|
240
|
-
├────────────────────┼────────────────────────────────────┼───────────────┤
|
|
241
|
-
│ Verificación │ pr-review-toolkit:code-reviewer │ OPUS │
|
|
242
|
-
│ (post-ejecución) │ pr-review-toolkit:silent-... │ OPUS │
|
|
243
|
-
│ │ pr-review-toolkit:pr-test-... │ OPUS │
|
|
244
|
-
│ │ (3 en paralelo obligatorio) │ │
|
|
245
|
-
└────────────────────┴────────────────────────────────────┴───────────────┘
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
### Por qué esta distribución
|
|
249
|
-
|
|
250
|
-
- **HAIKU para exploración:** Solo lee y mapea, no necesita razonamiento profundo
|
|
251
|
-
- **OPUS para implementación:** Escribe código, necesita máxima calidad
|
|
252
|
-
- **OPUS para verificación:** Análisis profundo de bugs y edge cases
|
|
253
|
-
</dispatcher_integration>
|
|
254
|
-
|
|
255
|
-
<agent_teams_integration>
|
|
256
|
-
## Agent Teams Integration (v4.0.0)
|
|
257
|
-
|
|
258
|
-
### Agent Teams: Método Obligatorio (v4.2.0)
|
|
259
|
-
|
|
260
|
-
**REGLA**: Agent Teams es OBLIGATORIO para todo trabajo paralelo de 2+ agentes.
|
|
261
|
-
La única excepción es exploración read-only (HAIKU).
|
|
262
|
-
|
|
263
|
-
```
|
|
264
|
-
┌─────────────────────────────────────────────────────────────────────────┐
|
|
265
|
-
│ AGENT TEAMS — OBLIGATORIO (v4.2.0) │
|
|
266
|
-
├─────────────────────────────────────────────────────────────────────────┤
|
|
267
|
-
│ FASE │ MÉTODO │
|
|
268
|
-
├─────────────────────────────────────┼───────────────────────────────────┤
|
|
269
|
-
│ Exploración (HAIKU read-only) │ SUBAGENTS (excepción) │
|
|
270
|
-
│ Implementación (2+ agentes) │ AGENT TEAMS (obligatorio) │
|
|
271
|
-
│ Verificación/Review (2+ agentes) │ AGENT TEAMS (obligatorio) │
|
|
272
|
-
│ Planning (2+ agentes opus) │ AGENT TEAMS (obligatorio) │
|
|
273
|
-
│ Debugging (2+ agentes) │ AGENT TEAMS (obligatorio) │
|
|
274
|
-
│ Agente único │ SUBAGENT (no aplica teams) │
|
|
275
|
-
└─────────────────────────────────────┴───────────────────────────────────┘
|
|
276
|
-
```
|
|
277
|
-
|
|
278
|
-
**VIOLACIÓN CRÍTICA**: Lanzar 2+ agentes sin TeamCreate = ABORTAR OPERACIÓN.
|
|
279
|
-
Ver `/references/enforcement-rules.md` Regla 8.
|
|
280
|
-
|
|
281
|
-
### Flujo con Agent Teams
|
|
282
|
-
|
|
283
|
-
```javascript
|
|
284
|
-
// 1. Crear team (API oficial Claude Code)
|
|
285
|
-
TeamCreate({
|
|
286
|
-
team_name: "elsabro-impl",
|
|
287
|
-
description: "Implementation team for: " + task
|
|
288
|
-
})
|
|
289
|
-
|
|
290
|
-
// 2. Create tasks para el team
|
|
291
|
-
TaskCreate({ subject: "Analyze requirements", ... })
|
|
292
|
-
TaskCreate({ subject: "Implement core logic", ... })
|
|
293
|
-
TaskCreate({ subject: "Write tests", ... })
|
|
294
|
-
|
|
295
|
-
// 3. Spawn teammates
|
|
296
|
-
Task({
|
|
297
|
-
subagent_type: "elsabro-executor",
|
|
298
|
-
team_name: "elsabro-impl",
|
|
299
|
-
name: "executor-1",
|
|
300
|
-
prompt: "Implement core logic following TDD..."
|
|
301
|
-
})
|
|
302
|
-
Task({
|
|
303
|
-
subagent_type: "elsabro-qa",
|
|
304
|
-
team_name: "elsabro-impl",
|
|
305
|
-
name: "qa-1",
|
|
306
|
-
prompt: "Write comprehensive tests..."
|
|
307
|
-
})
|
|
308
|
-
|
|
309
|
-
// 4. Teammates coordinate via SendMessage
|
|
310
|
-
// 5. When done, shutdown teammates then cleanup
|
|
311
|
-
SendMessage({ type: "shutdown_request", recipient: "executor-1", content: "Work complete" })
|
|
312
|
-
SendMessage({ type: "shutdown_request", recipient: "qa-1", content: "Work complete" })
|
|
313
|
-
TeamDelete()
|
|
314
|
-
```
|
|
315
|
-
|
|
316
|
-
### Limitations (Claude Code Official)
|
|
317
|
-
|
|
318
|
-
- **No session resumption**: `/resume` no restaura teammates in-process
|
|
319
|
-
- **No nested teams**: Teammates NO pueden crear sus propios teams
|
|
320
|
-
- **Lead es fijo**: La sesion que crea el team es el lead permanente
|
|
321
|
-
- **Un team por sesion**: Cleanup del actual antes de crear nuevo
|
|
322
|
-
- **Permissions at spawn**: Todos heredan permisos del lead
|
|
323
|
-
|
|
324
|
-
### Agentes que Migran a Agent Teams
|
|
325
|
-
|
|
326
|
-
| Agente | Rol en Team | Cuándo |
|
|
327
|
-
|--------|-------------|--------|
|
|
328
|
-
| elsabro-orchestrator | Team Lead | Siempre (coordina) |
|
|
329
|
-
| elsabro-executor | Teammate | Implementación |
|
|
330
|
-
| elsabro-planner | Teammate | Planning |
|
|
331
|
-
| elsabro-analyst | Teammate | Análisis |
|
|
332
|
-
| elsabro-qa | Teammate | Testing |
|
|
333
|
-
| elsabro-verifier | Teammate | Verificación |
|
|
334
|
-
| elsabro-debugger | Teammate | Debug (iter >= 2) |
|
|
335
|
-
|
|
336
|
-
### Excepciones (Subagents permitidos)
|
|
337
|
-
|
|
338
|
-
| Contexto | Razón |
|
|
339
|
-
|----------|-------|
|
|
340
|
-
| Exploración HAIKU (Paso 0) | Read-only, sin modificación de código |
|
|
341
|
-
| Agente único (quick mode) | Sin paralelismo, no aplica teams |
|
|
342
|
-
</agent_teams_integration>
|
|
343
|
-
|
|
344
|
-
<agent_teams_gate>
|
|
345
|
-
## Agent Teams Gate (OBLIGATORIO - NO NEGOCIABLE)
|
|
346
|
-
|
|
347
|
-
**ANTES de lanzar 2+ agentes para implementación o review, VERIFICAR:**
|
|
348
|
-
|
|
349
|
-
```
|
|
350
|
-
¿Se necesitan 2+ agentes en paralelo?
|
|
351
|
-
│
|
|
352
|
-
├─ SÍ → ¿Es exploración read-only (HAIKU)?
|
|
353
|
-
│ │
|
|
354
|
-
│ ├─ SÍ → Subagents OK (excepción)
|
|
355
|
-
│ │
|
|
356
|
-
│ └─ NO → ¿Se usó TeamCreate?
|
|
357
|
-
│ │
|
|
358
|
-
│ ├─ NO → EJECUTAR AHORA:
|
|
359
|
-
│ │ TeamCreate({ team_name, description })
|
|
360
|
-
│ │ Solo entonces: Task({ team_name, name, ... })
|
|
361
|
-
│ │
|
|
362
|
-
│ └─ SÍ → ¿Teammates spawned con team_name?
|
|
363
|
-
│ │
|
|
364
|
-
│ ├─ SÍ → Continuar con SendMessage para coordinación
|
|
365
|
-
│ └─ NO → VIOLACIÓN: Usar team_name en Task()
|
|
366
|
-
│
|
|
367
|
-
└─ NO (agente único) → Subagent OK
|
|
368
|
-
```
|
|
369
|
-
|
|
370
|
-
```javascript
|
|
371
|
-
// MARCAR: Agent Teams fue usado correctamente (para GATE CHECK en siguiente_paso)
|
|
372
|
-
state.current_flow.parallel_agents_used = agentCount; // número de agentes lanzados
|
|
373
|
-
state.current_flow.agent_teams_used = true;
|
|
374
|
-
Write(".elsabro/state.json", JSON.stringify(state, null, 2));
|
|
375
|
-
```
|
|
376
|
-
|
|
377
|
-
**VIOLACIÓN CRÍTICA**: Lanzar 2+ agentes sin Agent Teams = ABORTAR OPERACIÓN
|
|
378
|
-
</agent_teams_gate>
|
|
379
|
-
|
|
380
|
-
<blocking_review_protocol>
|
|
381
|
-
## Protocolo de Review Bloqueante (v4.0.0)
|
|
382
|
-
|
|
383
|
-
**REGLA CRÍTICA:** El proceso NO PUEDE avanzar a post-mortem si hay issues de code review sin resolver.
|
|
384
|
-
|
|
385
|
-
### Flujo
|
|
386
|
-
|
|
387
|
-
```
|
|
388
|
-
parallel_review (3 agentes)
|
|
389
|
-
↓
|
|
390
|
-
review_check: ¿hay issues?
|
|
391
|
-
↓
|
|
392
|
-
┌────┴────┐
|
|
393
|
-
│ NO │ YES
|
|
394
|
-
│ issues │ issues
|
|
395
|
-
↓ ↓
|
|
396
|
-
verify fix_review_issues
|
|
397
|
-
final (max 5 iteraciones)
|
|
398
|
-
↓
|
|
399
|
-
parallel_review (re-check)
|
|
400
|
-
↓
|
|
401
|
-
¿issues == 0?
|
|
402
|
-
↓
|
|
403
|
-
┌─────┴─────┐
|
|
404
|
-
│ SÍ │ NO (5 iter agotadas)
|
|
405
|
-
↓ ↓
|
|
406
|
-
verify_final interrupt_blocked
|
|
407
|
-
(SIN opción "continuar con errores")
|
|
408
|
-
↓
|
|
409
|
-
┌───┴───┐───────┐
|
|
410
|
-
│ │ │
|
|
411
|
-
retry manual abort
|
|
412
|
-
↓ ↓ ↓
|
|
413
|
-
fix_review wait end_cancelled
|
|
414
|
-
_issues _manual
|
|
415
|
-
_review_fix
|
|
416
|
-
↓
|
|
417
|
-
parallel_review (re-check)
|
|
418
|
-
```
|
|
419
|
-
|
|
420
|
-
### Escape Hatches ELIMINADOS
|
|
421
|
-
|
|
422
|
-
Los siguientes escape hatches han sido removidos en v4.0.0:
|
|
423
|
-
|
|
424
|
-
1. ~~`onMaxIterations: "verify_final"`~~ → Ahora va a `interrupt_blocked` (sin opción de continuar)
|
|
425
|
-
2. ~~`"skip": "Continuar sin fix"`~~ → Removido de `interrupt_manual_fix`
|
|
426
|
-
3. ~~`"accept": "Aceptar con errores"`~~ → Removido de `interrupt_verification_failed`
|
|
427
|
-
|
|
428
|
-
### Iteraciones de Review
|
|
429
|
-
|
|
430
|
-
```javascript
|
|
431
|
-
// Estado del review loop
|
|
432
|
-
state.reviewIteration = state.reviewIteration || 0;
|
|
433
|
-
state.reviewIteration++;
|
|
434
|
-
|
|
435
|
-
// Log de cada iteración
|
|
436
|
-
console.log(`[REVIEW] Iteración ${state.reviewIteration}/5`);
|
|
437
|
-
console.log(`[REVIEW] Issues encontrados: ${issueCount}`);
|
|
438
|
-
|
|
439
|
-
// Solo avanza cuando issues == 0
|
|
440
|
-
if (issueCount === 0) {
|
|
441
|
-
state.reviewIteration = 0; // Reset
|
|
442
|
-
// → verify_final
|
|
443
|
-
} else if (state.reviewIteration >= 5) {
|
|
444
|
-
// → interrupt_blocked (NO verify_final)
|
|
445
|
-
} else {
|
|
446
|
-
// → fix_review_issues → parallel_review
|
|
447
|
-
}
|
|
448
|
-
```
|
|
449
|
-
</blocking_review_protocol>
|
|
450
|
-
|
|
451
|
-
<process>
|
|
452
|
-
## Paso 0: Exploración Pre-Ejecución (HAIKU x3 paralelo)
|
|
453
|
-
|
|
454
|
-
**OBLIGATORIO:** Antes de ejecutar, explorar el codebase para entender contexto.
|
|
455
|
-
|
|
456
|
-
```javascript
|
|
457
|
-
// Crear tasks de exploración
|
|
458
|
-
TaskCreate({
|
|
459
|
-
subject: "Explore: Find related files",
|
|
460
|
-
description: "Buscar archivos relacionados con la fase",
|
|
461
|
-
activeForm: "Buscando archivos...",
|
|
462
|
-
metadata: { type: "exploration", model: "haiku" }
|
|
463
|
-
}) // → explore-files-id
|
|
464
|
-
|
|
465
|
-
TaskCreate({
|
|
466
|
-
subject: "Explore: Analyze patterns",
|
|
467
|
-
description: "Analizar patrones existentes en el codebase",
|
|
468
|
-
activeForm: "Analizando patrones...",
|
|
469
|
-
metadata: { type: "exploration", model: "haiku" }
|
|
470
|
-
}) // → explore-patterns-id
|
|
471
|
-
|
|
472
|
-
TaskCreate({
|
|
473
|
-
subject: "Explore: Map architecture",
|
|
474
|
-
description: "Mapear arquitectura del área afectada",
|
|
475
|
-
activeForm: "Mapeando arquitectura...",
|
|
476
|
-
metadata: { type: "exploration", model: "haiku" }
|
|
477
|
-
}) // → explore-arch-id
|
|
478
|
-
|
|
479
|
-
// Marcar todas como in_progress
|
|
480
|
-
TaskUpdate({ taskId: "explore-files-id", status: "in_progress" })
|
|
481
|
-
TaskUpdate({ taskId: "explore-patterns-id", status: "in_progress" })
|
|
482
|
-
TaskUpdate({ taskId: "explore-arch-id", status: "in_progress" })
|
|
483
|
-
|
|
484
|
-
// Lanzar 3 agentes HAIKU EN PARALELO (UN SOLO MENSAJE)
|
|
485
|
-
Task({
|
|
486
|
-
subagent_type: "Explore",
|
|
487
|
-
model: "haiku",
|
|
488
|
-
description: "Buscar archivos relacionados",
|
|
489
|
-
prompt: "Busca archivos relacionados con la fase [N]. Lista los 10 más relevantes."
|
|
490
|
-
}) |
|
|
491
|
-
Task({
|
|
492
|
-
subagent_type: "feature-dev:code-explorer",
|
|
493
|
-
model: "haiku",
|
|
494
|
-
description: "Analizar patrones",
|
|
495
|
-
prompt: "Analiza patrones de arquitectura en el área de la fase [N]."
|
|
496
|
-
}) |
|
|
497
|
-
Task({
|
|
498
|
-
subagent_type: "Plan",
|
|
499
|
-
model: "haiku",
|
|
500
|
-
description: "Mapear arquitectura",
|
|
501
|
-
prompt: "Mapea componentes y flujo de datos del área afectada."
|
|
502
|
-
})
|
|
503
|
-
|
|
504
|
-
// Marcar completed
|
|
505
|
-
TaskUpdate({ taskId: "explore-files-id", status: "completed" })
|
|
506
|
-
TaskUpdate({ taskId: "explore-patterns-id", status: "completed" })
|
|
507
|
-
TaskUpdate({ taskId: "explore-arch-id", status: "completed" })
|
|
508
|
-
```
|
|
509
|
-
|
|
510
|
-
**Resultado:** Contexto del codebase capturado antes de modificar nada.
|
|
511
|
-
|
|
512
|
-
## Paso 1: Descubrir Planes
|
|
34
|
+
Leer `.elsabro/state.json` siguiendo el protocolo de @references/state-sync.md.
|
|
35
|
+
Verificar flujo en progreso. Actualizar phase a "stepping".
|
|
513
36
|
|
|
514
37
|
```bash
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
Encontrar planes para la fase especificada.
|
|
519
|
-
|
|
520
|
-
## Paso 2: Crear Estructura de Tasks
|
|
521
|
-
|
|
522
|
-
### 2.1 Crear Task coordinadora de fase
|
|
523
|
-
```javascript
|
|
524
|
-
TaskCreate({
|
|
525
|
-
subject: "Execute Phase [N]",
|
|
526
|
-
description: "Coordinar ejecución de todos los planes de la fase",
|
|
527
|
-
activeForm: "Ejecutando Fase [N]...",
|
|
528
|
-
metadata: { phase: N, type: "coordinator" }
|
|
529
|
-
}) // → phase-coordinator-id
|
|
530
|
-
```
|
|
531
|
-
|
|
532
|
-
### 2.2 Organizar por Waves y crear Tasks
|
|
533
|
-
Leer frontmatter de cada plan para agrupar por `wave`:
|
|
534
|
-
|
|
535
|
-
```javascript
|
|
536
|
-
// Para cada wave, crear task coordinadora
|
|
537
|
-
TaskCreate({
|
|
538
|
-
subject: "Execute Wave [W]",
|
|
539
|
-
description: "Plans: A, B, C en paralelo",
|
|
540
|
-
activeForm: "Ejecutando Wave [W]...",
|
|
541
|
-
metadata: { wave: W, plans: ["A", "B", "C"] }
|
|
542
|
-
}) // → wave-W-id
|
|
543
|
-
|
|
544
|
-
// Wave 2+ tiene dependencia de wave anterior
|
|
545
|
-
TaskUpdate({
|
|
546
|
-
taskId: "wave-2-id",
|
|
547
|
-
addBlockedBy: ["wave-1-id"]
|
|
548
|
-
})
|
|
549
|
-
```
|
|
550
|
-
|
|
551
|
-
### 2.3 Crear Tasks por plan dentro de cada wave
|
|
552
|
-
```javascript
|
|
553
|
-
TaskCreate({
|
|
554
|
-
subject: "Execute Plan [name]",
|
|
555
|
-
description: "TDD + commits para plan específico",
|
|
556
|
-
activeForm: "Ejecutando Plan [name]...",
|
|
557
|
-
metadata: { wave: W, plan: "name", type: "executor" }
|
|
558
|
-
}) // → plan-X-id
|
|
559
|
-
|
|
560
|
-
// Bloquear por wave coordinator
|
|
561
|
-
TaskUpdate({
|
|
562
|
-
taskId: "plan-X-id",
|
|
563
|
-
addBlockedBy: ["wave-W-id"]
|
|
564
|
-
})
|
|
565
|
-
```
|
|
566
|
-
|
|
567
|
-
## Paso 3: Ejecutar Waves con Tracking
|
|
568
|
-
|
|
569
|
-
Para cada wave:
|
|
570
|
-
|
|
571
|
-
### Marcar wave como in_progress
|
|
572
|
-
```javascript
|
|
573
|
-
TaskUpdate({ taskId: "wave-W-id", status: "in_progress" })
|
|
574
|
-
```
|
|
575
|
-
|
|
576
|
-
<IMPERATIVO_AGENT_TEAMS>
|
|
577
|
-
## ⛔ STOP — LEER ANTES DE LANZAR AGENTES PARALELOS
|
|
578
|
-
|
|
579
|
-
**REGLA NO NEGOCIABLE (Rule 8):** Si vas a lanzar 2+ Task() para implementacion o review:
|
|
580
|
-
|
|
581
|
-
1. **PRIMERO** → `TeamCreate({ team_name: "elsabro-impl", description: "..." })`
|
|
582
|
-
2. **DESPUES** → `Task({ ..., team_name: "elsabro-impl", name: "executor-1" })`
|
|
583
|
-
3. **AL FINAL** → `SendMessage({ type: "shutdown_request", ... })` para CADA teammate
|
|
584
|
-
4. **ULTIMO** → `TeamDelete()`
|
|
585
|
-
|
|
586
|
-
**Si ya lanzaste Task() sin TeamCreate: DETENTE AHORA. No continúes.**
|
|
587
|
-
Vuelve arriba, crea el team, y relanza los agentes CON team_name.
|
|
588
|
-
|
|
589
|
-
**NUNCA hagas esto:**
|
|
590
|
-
```javascript
|
|
591
|
-
// ⛔ PROHIBIDO — bare Task() sin team
|
|
592
|
-
Task({ subagent_type: "elsabro-executor", prompt: "..." })
|
|
593
|
-
Task({ subagent_type: "elsabro-qa", prompt: "..." })
|
|
594
|
-
```
|
|
595
|
-
|
|
596
|
-
**SIEMPRE haz esto:**
|
|
597
|
-
```javascript
|
|
598
|
-
// ✅ CORRECTO — con Agent Team
|
|
599
|
-
TeamCreate({ team_name: "elsabro-impl", description: "Implementation" })
|
|
600
|
-
Task({ subagent_type: "elsabro-executor", team_name: "elsabro-impl", name: "executor-1", prompt: "..." })
|
|
601
|
-
Task({ subagent_type: "elsabro-qa", team_name: "elsabro-impl", name: "qa-1", prompt: "..." })
|
|
602
|
-
// ... al completar ...
|
|
603
|
-
SendMessage({ type: "shutdown_request", recipient: "executor-1", content: "Done" })
|
|
604
|
-
SendMessage({ type: "shutdown_request", recipient: "qa-1", content: "Done" })
|
|
605
|
-
TeamDelete()
|
|
606
|
-
```
|
|
607
|
-
|
|
608
|
-
**Excepcion UNICA:** Exploracion read-only con HAIKU (Paso 0) puede usar subagents sueltos.
|
|
609
|
-
</IMPERATIVO_AGENT_TEAMS>
|
|
610
|
-
|
|
611
|
-
### Si hay múltiples planes en la wave → Paralelo (OPUS)
|
|
612
|
-
```javascript
|
|
613
|
-
// Marcar todos los planes como in_progress
|
|
614
|
-
TaskUpdate({ taskId: "plan-A-id", status: "in_progress" })
|
|
615
|
-
TaskUpdate({ taskId: "plan-B-id", status: "in_progress" })
|
|
616
|
-
TaskUpdate({ taskId: "plan-C-id", status: "in_progress" })
|
|
617
|
-
|
|
618
|
-
// OBLIGATORIO: Crear Agent Team para implementación paralela (Rule 8)
|
|
619
|
-
TeamCreate({
|
|
620
|
-
team_name: "elsabro-impl",
|
|
621
|
-
description: "Implementation team for wave " + waveNumber
|
|
622
|
-
})
|
|
623
|
-
|
|
624
|
-
// MARCAR: Agent Teams usado (para GATE CHECK en siguiente_paso)
|
|
625
|
-
state.current_flow.parallel_agents_used = 3;
|
|
626
|
-
state.current_flow.agent_teams_used = true;
|
|
627
|
-
Write(".elsabro/state.json", JSON.stringify(state, null, 2));
|
|
628
|
-
|
|
629
|
-
// Lanzar teammates OPUS en paralelo (UN SOLO MENSAJE)
|
|
630
|
-
// MODELO: OPUS porque escriben código
|
|
631
|
-
// SKILLS: Incluir loaded_skills en CADA prompt de executor
|
|
632
|
-
const skillContext = state.context.loaded_skills?.length > 0
|
|
633
|
-
? '\n\n## SKILLS DE REFERENCIA\n' + state.context.loaded_skills.map(s =>
|
|
634
|
-
'### Skill: ' + s.name + '\n' + s.content
|
|
635
|
-
).join('\n\n---\n\n') + '\n\nUsa los skills como referencia de patrones y estructura de archivos.'
|
|
636
|
-
: '';
|
|
637
|
-
|
|
638
|
-
Task({
|
|
639
|
-
subagent_type: "elsabro-executor",
|
|
640
|
-
model: "opus", // ← OPUS para implementación
|
|
641
|
-
team_name: "elsabro-impl",
|
|
642
|
-
name: "executor-1",
|
|
643
|
-
description: "Ejecutar Plan A",
|
|
644
|
-
prompt: `Implementa el Plan A siguiendo TDD.${skillContext}`
|
|
645
|
-
}) |
|
|
646
|
-
Task({
|
|
647
|
-
subagent_type: "elsabro-executor",
|
|
648
|
-
model: "opus", // ← OPUS para implementación
|
|
649
|
-
team_name: "elsabro-impl",
|
|
650
|
-
name: "executor-2",
|
|
651
|
-
description: "Ejecutar Plan B",
|
|
652
|
-
prompt: `Implementa el Plan B siguiendo TDD.${skillContext}`
|
|
653
|
-
}) |
|
|
654
|
-
Task({
|
|
655
|
-
subagent_type: "elsabro-executor",
|
|
656
|
-
model: "opus", // ← OPUS para implementación
|
|
657
|
-
team_name: "elsabro-impl",
|
|
658
|
-
name: "executor-3",
|
|
659
|
-
description: "Ejecutar Plan C",
|
|
660
|
-
prompt: `Implementa el Plan C siguiendo TDD.${skillContext}`
|
|
661
|
-
})
|
|
662
|
-
|
|
663
|
-
// Al completar cada plan
|
|
664
|
-
TaskUpdate({ taskId: "plan-A-id", status: "completed" })
|
|
665
|
-
```
|
|
666
|
-
|
|
667
|
-
### Validación arquitectónica en paralelo (OPUS x2)
|
|
668
|
-
```javascript
|
|
669
|
-
// OBLIGATORIO: Crear Agent Team para validación arquitectónica (Rule 8)
|
|
670
|
-
TeamCreate({
|
|
671
|
-
team_name: "elsabro-arch-validate",
|
|
672
|
-
description: "Architectural validation: implementation + architecture review"
|
|
673
|
-
})
|
|
674
|
-
|
|
675
|
-
// Spawn 2 teammates OPUS en paralelo
|
|
676
|
-
Task({
|
|
677
|
-
subagent_type: "elsabro-executor",
|
|
678
|
-
model: "opus",
|
|
679
|
-
team_name: "elsabro-arch-validate",
|
|
680
|
-
name: "impl-1",
|
|
681
|
-
description: "Implementar cambios",
|
|
682
|
-
prompt: "..."
|
|
683
|
-
}) |
|
|
684
|
-
Task({
|
|
685
|
-
subagent_type: "feature-dev:code-architect",
|
|
686
|
-
model: "opus", // ← OPUS para decisiones arquitectónicas
|
|
687
|
-
team_name: "elsabro-arch-validate",
|
|
688
|
-
name: "architect-1",
|
|
689
|
-
description: "Validar arquitectura",
|
|
690
|
-
prompt: "Verifica que la implementación sigue los patrones del codebase..."
|
|
691
|
-
})
|
|
692
|
-
|
|
693
|
-
// Shutdown y cleanup
|
|
694
|
-
SendMessage({ type: "shutdown_request", recipient: "impl-1", content: "Validation complete" })
|
|
695
|
-
SendMessage({ type: "shutdown_request", recipient: "architect-1", content: "Validation complete" })
|
|
696
|
-
TeamDelete()
|
|
697
|
-
```
|
|
698
|
-
|
|
699
|
-
### Si solo hay un plan → Secuencial (OPUS)
|
|
700
|
-
```javascript
|
|
701
|
-
TaskUpdate({ taskId: "plan-X-id", status: "in_progress" })
|
|
702
|
-
Task({
|
|
703
|
-
subagent_type: "elsabro-executor",
|
|
704
|
-
model: "opus", // ← OPUS porque escribe código
|
|
705
|
-
description: "Ejecutar plan único",
|
|
706
|
-
prompt: "..."
|
|
707
|
-
})
|
|
708
|
-
TaskUpdate({ taskId: "plan-X-id", status: "completed" })
|
|
709
|
-
```
|
|
710
|
-
|
|
711
|
-
### Marcar wave como completed cuando todos sus planes terminen
|
|
712
|
-
```javascript
|
|
713
|
-
TaskUpdate({ taskId: "wave-W-id", status: "completed" })
|
|
714
|
-
// → Wave W+1 se desbloquea automáticamente
|
|
715
|
-
|
|
716
|
-
// MARCAR: código fue escrito (para code_review_gate)
|
|
717
|
-
state.current_flow.code_written = true;
|
|
718
|
-
Write(".elsabro/state.json", JSON.stringify(state, null, 2));
|
|
719
|
-
```
|
|
720
|
-
|
|
721
|
-
## Paso 4: Verificar Fase (con Agregador)
|
|
722
|
-
|
|
723
|
-
### 4.1 Crear tasks de verificación
|
|
724
|
-
```javascript
|
|
725
|
-
TaskCreate({
|
|
726
|
-
subject: "Verify Functional Requirements",
|
|
727
|
-
activeForm: "Verificando funcionalidad...",
|
|
728
|
-
metadata: { type: "verifier", area: "functional" }
|
|
729
|
-
}) // → verify-functional-id
|
|
730
|
-
|
|
731
|
-
TaskCreate({
|
|
732
|
-
subject: "Verify Quality Metrics",
|
|
733
|
-
activeForm: "Verificando calidad...",
|
|
734
|
-
metadata: { type: "verifier", area: "quality" }
|
|
735
|
-
}) // → verify-quality-id
|
|
736
|
-
|
|
737
|
-
TaskCreate({
|
|
738
|
-
subject: "Verify Phase Completion",
|
|
739
|
-
activeForm: "Agregando resultados...",
|
|
740
|
-
metadata: { type: "aggregator" }
|
|
741
|
-
}) // → verify-aggregate-id
|
|
742
|
-
|
|
743
|
-
// Agregador espera a todos los verificadores
|
|
744
|
-
TaskUpdate({
|
|
745
|
-
taskId: "verify-aggregate-id",
|
|
746
|
-
addBlockedBy: ["verify-functional-id", "verify-quality-id"]
|
|
747
|
-
})
|
|
748
|
-
```
|
|
749
|
-
|
|
750
|
-
### 4.2 Ejecutar verificación en paralelo (OPUS x3)
|
|
751
|
-
|
|
752
|
-
**OBLIGATORIO:** Usar 3 agentes OPUS para verificación profunda.
|
|
753
|
-
|
|
754
|
-
```javascript
|
|
755
|
-
// Crear task adicional de seguridad
|
|
756
|
-
TaskCreate({
|
|
757
|
-
subject: "Verify Security & Edge Cases",
|
|
758
|
-
activeForm: "Verificando seguridad...",
|
|
759
|
-
metadata: { type: "verifier", area: "security", model: "opus" }
|
|
760
|
-
}) // → verify-security-id
|
|
761
|
-
|
|
762
|
-
// Actualizar agregador para esperar los 3
|
|
763
|
-
TaskUpdate({
|
|
764
|
-
taskId: "verify-aggregate-id",
|
|
765
|
-
addBlockedBy: ["verify-functional-id", "verify-quality-id", "verify-security-id"]
|
|
766
|
-
})
|
|
767
|
-
|
|
768
|
-
// Marcar todos como in_progress
|
|
769
|
-
TaskUpdate({ taskId: "verify-functional-id", status: "in_progress" })
|
|
770
|
-
TaskUpdate({ taskId: "verify-quality-id", status: "in_progress" })
|
|
771
|
-
TaskUpdate({ taskId: "verify-security-id", status: "in_progress" })
|
|
772
|
-
|
|
773
|
-
// NOTA: El Agent Team "elsabro-impl" ya fue creado en Paso 3.
|
|
774
|
-
// Reusar el mismo team para la fase de review (un team por sesión).
|
|
775
|
-
// Si el team fue eliminado, crear uno nuevo:
|
|
776
|
-
// TeamCreate({ team_name: "elsabro-review", description: "Review team" })
|
|
777
|
-
|
|
778
|
-
// Lanzar 3 reviewers como teammates EN PARALELO (UN SOLO MENSAJE)
|
|
779
|
-
Task({
|
|
780
|
-
subagent_type: "pr-review-toolkit:code-reviewer",
|
|
781
|
-
model: "opus", // ← OPUS para análisis profundo
|
|
782
|
-
team_name: "elsabro-impl",
|
|
783
|
-
name: "reviewer-1",
|
|
784
|
-
description: "Code review completo",
|
|
785
|
-
prompt: "Revisa los cambios buscando bugs, code smells, mejores prácticas..."
|
|
786
|
-
}) |
|
|
787
|
-
Task({
|
|
788
|
-
subagent_type: "pr-review-toolkit:silent-failure-hunter",
|
|
789
|
-
model: "opus", // ← OPUS para edge cases
|
|
790
|
-
team_name: "elsabro-impl",
|
|
791
|
-
name: "reviewer-2",
|
|
792
|
-
description: "Buscar errores ocultos",
|
|
793
|
-
prompt: "Busca errores silenciosos, try/catch que ocultan errores, fallbacks problemáticos..."
|
|
794
|
-
}) |
|
|
795
|
-
Task({
|
|
796
|
-
subagent_type: "pr-review-toolkit:pr-test-analyzer",
|
|
797
|
-
model: "opus", // ← OPUS para análisis de tests
|
|
798
|
-
team_name: "elsabro-impl",
|
|
799
|
-
name: "reviewer-3",
|
|
800
|
-
description: "Analizar cobertura de tests",
|
|
801
|
-
prompt: "Verifica que los tests cubren los cambios, busca casos críticos sin test..."
|
|
802
|
-
})
|
|
803
|
-
|
|
804
|
-
// Marcar completed al terminar
|
|
805
|
-
TaskUpdate({ taskId: "verify-functional-id", status: "completed" })
|
|
806
|
-
TaskUpdate({ taskId: "verify-quality-id", status: "completed" })
|
|
807
|
-
TaskUpdate({ taskId: "verify-security-id", status: "completed" })
|
|
808
|
-
|
|
809
|
-
// Agregador se desbloquea y genera reporte final
|
|
810
|
-
TaskUpdate({ taskId: "verify-aggregate-id", status: "in_progress" })
|
|
811
|
-
// ... genera VERIFICATION.md ...
|
|
812
|
-
TaskUpdate({ taskId: "verify-aggregate-id", status: "completed" })
|
|
813
|
-
|
|
814
|
-
// MARCAR: code review pasó (para code_review_gate en siguiente_paso)
|
|
815
|
-
if (reviewIssuesCount === 0) {
|
|
816
|
-
state.current_flow.code_review_passed = true;
|
|
817
|
-
Write(".elsabro/state.json", JSON.stringify(state, null, 2));
|
|
818
|
-
}
|
|
819
|
-
```
|
|
820
|
-
|
|
821
|
-
## Paso 5: Manejar Resultados
|
|
822
|
-
|
|
823
|
-
### Si passed:
|
|
824
|
-
```
|
|
825
|
-
✓ Fase [N] completada
|
|
826
|
-
|
|
827
|
-
Lo que se hizo:
|
|
828
|
-
- [Resumen de tareas]
|
|
829
|
-
|
|
830
|
-
Archivos modificados:
|
|
831
|
-
- [Lista de archivos]
|
|
832
|
-
|
|
833
|
-
Commits creados:
|
|
834
|
-
- [Lista de commits]
|
|
835
|
-
|
|
836
|
-
¿Siguiente paso?
|
|
837
|
-
- Continuar con fase [N+1]: /elsabro:plan [N+1]
|
|
838
|
-
- Verificar manualmente: /elsabro:verify [N]
|
|
839
|
-
```
|
|
840
|
-
|
|
841
|
-
### Si gaps_found:
|
|
842
|
-
```
|
|
843
|
-
⚠ Fase [N] tiene gaps
|
|
844
|
-
|
|
845
|
-
Problemas encontrados:
|
|
846
|
-
- [Gap 1]
|
|
847
|
-
- [Gap 2]
|
|
848
|
-
|
|
849
|
-
Opciones:
|
|
850
|
-
1. Crear planes de corrección: /elsabro:plan [N] --gaps
|
|
851
|
-
2. Ver detalles: cat .planning/[N]-VERIFICATION.md
|
|
852
|
-
3. Continuar de todas formas
|
|
853
|
-
```
|
|
854
|
-
|
|
855
|
-
### Si human_needed:
|
|
856
|
-
```
|
|
857
|
-
👤 Se necesita verificación manual
|
|
858
|
-
|
|
859
|
-
Por favor prueba:
|
|
860
|
-
1. [Instrucción]
|
|
861
|
-
2. [Instrucción]
|
|
862
|
-
|
|
863
|
-
Cuando termines, dime si funcionó o qué problemas encontraste.
|
|
864
|
-
```
|
|
865
|
-
|
|
866
|
-
</process>
|
|
867
|
-
|
|
868
|
-
<agent_teams_cleanup>
|
|
869
|
-
## Agent Teams Cleanup (OBLIGATORIO)
|
|
870
|
-
|
|
871
|
-
**Al completar TODAS las fases de implementacion y review:**
|
|
872
|
-
|
|
873
|
-
```javascript
|
|
874
|
-
// 1. Shutdown CADA teammate por nombre
|
|
875
|
-
const teammates = ["executor-1", "executor-2", "executor-3", "reviewer-1", "reviewer-2", "reviewer-3"];
|
|
876
|
-
for (const name of teammates) {
|
|
877
|
-
SendMessage({ type: "shutdown_request", recipient: name, content: "All phases complete" });
|
|
878
|
-
}
|
|
879
|
-
|
|
880
|
-
// 2. Eliminar team
|
|
881
|
-
TeamDelete();
|
|
882
|
-
|
|
883
|
-
// 3. Registrar en state
|
|
884
|
-
state.current_flow.agent_teams_cleanup = true;
|
|
885
|
-
Write(".elsabro/state.json", JSON.stringify(state, null, 2));
|
|
886
|
-
```
|
|
887
|
-
|
|
888
|
-
**GATE**: No mostrar "Siguiente Paso" si agent_teams_cleanup !== true y hubo 2+ agentes.
|
|
889
|
-
</agent_teams_cleanup>
|
|
890
|
-
|
|
891
|
-
<code_review_gate>
|
|
892
|
-
## Code Review Gate (OBLIGATORIO - NO NEGOCIABLE)
|
|
893
|
-
|
|
894
|
-
**ANTES de mostrar "Siguiente Paso" o ofrecer commit, VERIFICAR:**
|
|
895
|
-
|
|
896
|
-
```
|
|
897
|
-
¿Se escribió/modificó código en este comando?
|
|
898
|
-
│
|
|
899
|
-
├─ NO → Continuar a Siguiente Paso
|
|
900
|
-
│
|
|
901
|
-
└─ SÍ → ¿Se ejecutó code review (Paso 4)?
|
|
902
|
-
│
|
|
903
|
-
├─ NO → ABORTAR. Volver a Paso 4.
|
|
904
|
-
│
|
|
905
|
-
└─ SÍ, issues == 0 → Continuar a Siguiente Paso
|
|
906
|
-
```
|
|
907
|
-
|
|
908
|
-
**VIOLACIÓN CRÍTICA**: Mostrar siguiente paso sin code review = ABORTAR OPERACIÓN
|
|
909
|
-
</code_review_gate>
|
|
910
|
-
|
|
911
|
-
<siguiente_paso>
|
|
912
|
-
## Siguiente Paso
|
|
913
|
-
|
|
914
|
-
### Self-Check (OBLIGATORIO antes de reportar resultado)
|
|
915
|
-
|
|
916
|
-
Antes de mostrar "Siguiente Paso", verifica CADA UNO de estos items:
|
|
917
|
-
|
|
918
|
-
```
|
|
919
|
-
[ ] Si lance 2+ Task() en paralelo → ¿use TeamCreate primero?
|
|
920
|
-
SI: Continuar
|
|
921
|
-
NO: DETENERME. Crear team y relanzar.
|
|
922
|
-
|
|
923
|
-
[ ] Si descubri skills relevantes → ¿los cargue con Read() y los pase al executor?
|
|
924
|
-
SI: Continuar
|
|
925
|
-
NO: DETENERME. Cargar skills y re-ejecutar.
|
|
926
|
-
|
|
927
|
-
[ ] Si escribi/modifique codigo → ¿ejecute code review?
|
|
928
|
-
SI: Continuar
|
|
929
|
-
NO: DETENERME. Ejecutar code review.
|
|
930
|
-
|
|
931
|
-
[ ] Si use Agent Teams → ¿ejecute SendMessage(shutdown) + TeamDelete?
|
|
932
|
-
SI: Continuar
|
|
933
|
-
NO: DETENERME. Hacer cleanup.
|
|
934
|
-
```
|
|
935
|
-
|
|
936
|
-
**Si alguna respuesta es NO: NO mostrar siguiente paso. Corregir primero.**
|
|
937
|
-
|
|
938
|
-
Al completar, establecer en state.json:
|
|
939
|
-
```javascript
|
|
940
|
-
// GATE CHECK 1: No escribir suggested_next sin code review
|
|
941
|
-
if (state.current_flow?.code_written && !state.current_flow?.code_review_passed) {
|
|
942
|
-
// VIOLACIÓN CRÍTICA — ABORTAR. Volver a code_review_gate.
|
|
943
|
-
throw new Error("CODE_REVIEW_GATE: Cannot proceed without code review");
|
|
944
|
-
}
|
|
945
|
-
// GATE CHECK 2: No proceder sin Agent Teams para fases con 2+ agentes
|
|
946
|
-
if (state.current_flow?.parallel_agents_used >= 2 && !state.current_flow?.agent_teams_used) {
|
|
947
|
-
// VIOLACIÓN CRÍTICA — ABORTAR. Volver a agent_teams_gate.
|
|
948
|
-
throw new Error("AGENT_TEAMS_GATE: Cannot proceed without Agent Teams for 2+ agents");
|
|
949
|
-
}
|
|
950
|
-
state.suggested_next = "verify-work";
|
|
951
|
-
Write(".elsabro/state.json", JSON.stringify(state, null, 2));
|
|
952
|
-
```
|
|
953
|
-
|
|
954
|
-
Mostrar al usuario:
|
|
955
|
-
```
|
|
956
|
-
## Siguiente Paso
|
|
38
|
+
FLOW="flows/development-flow.json"
|
|
39
|
+
TASK="[descripcion de la tarea del usuario]"
|
|
40
|
+
PROFILE="[default|yolo|careful|teams|bmad]"
|
|
957
41
|
|
|
958
|
-
|
|
959
|
-
→ /elsabro:progress — ver el progreso general del proyecto
|
|
42
|
+
node flow-engine/src/cli.js init --flow "$FLOW" --task "$TASK" --profile "$PROFILE"
|
|
960
43
|
```
|
|
961
|
-
</siguiente_paso>
|
|
962
44
|
|
|
963
|
-
|
|
964
|
-
## Protocolo de Ejecución
|
|
45
|
+
Guardar el flowId del resultado para todos los comandos siguientes.
|
|
965
46
|
|
|
966
|
-
|
|
47
|
+
## 2. Loop Principal
|
|
967
48
|
|
|
968
|
-
|
|
969
|
-
- Si usa librería específica → Verificar patrón actual
|
|
49
|
+
Ejecutar el siguiente loop hasta que `step` retorne `{ finished: true }`:
|
|
970
50
|
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
-
|
|
974
|
-
- Configuración → NO
|
|
975
|
-
- UI simple → NO
|
|
976
|
-
|
|
977
|
-
3. **Si TDD:**
|
|
978
|
-
```
|
|
979
|
-
a. Escribir test que falla
|
|
980
|
-
b. Verificar que falla por razón correcta
|
|
981
|
-
c. Implementar código mínimo
|
|
982
|
-
d. Verificar que test pasa
|
|
983
|
-
e. Refactorizar si necesario
|
|
984
|
-
f. Commit
|
|
985
|
-
```
|
|
986
|
-
|
|
987
|
-
4. **Si no TDD:**
|
|
51
|
+
1. **STEP**: Ejecutar con Bash y parsear el JSON:
|
|
52
|
+
```bash
|
|
53
|
+
node flow-engine/src/cli.js step --flow "$FLOW"
|
|
988
54
|
```
|
|
989
|
-
|
|
990
|
-
b. Ejecutar <verify>
|
|
991
|
-
c. Confirmar resultado esperado
|
|
992
|
-
d. Commit
|
|
993
|
-
```
|
|
994
|
-
|
|
995
|
-
### Commit por Tarea
|
|
996
|
-
|
|
997
|
-
```bash
|
|
998
|
-
git add [archivos]
|
|
999
|
-
git commit -m "feat([fase]-[plan]): [descripción]"
|
|
1000
|
-
```
|
|
1001
|
-
</execution_protocol>
|
|
1002
|
-
|
|
1003
|
-
<parallel_execution>
|
|
1004
|
-
## Ejecución Paralela con Tasks
|
|
1005
|
-
|
|
1006
|
-
### Cuándo usar paralelo
|
|
1007
|
-
- Múltiples planes en la misma wave
|
|
1008
|
-
- Tareas independientes (sin dependencias)
|
|
1009
|
-
|
|
1010
|
-
### Cómo paralelizar CON TRACKING
|
|
1011
|
-
```javascript
|
|
1012
|
-
// 1. Crear tasks para cada plan
|
|
1013
|
-
const planATask = TaskCreate({ subject: "Plan A", activeForm: "Ejecutando Plan A..." })
|
|
1014
|
-
const planBTask = TaskCreate({ subject: "Plan B", activeForm: "Ejecutando Plan B..." })
|
|
1015
|
-
const planCTask = TaskCreate({ subject: "Plan C", activeForm: "Ejecutando Plan C..." })
|
|
1016
|
-
|
|
1017
|
-
// 2. Marcar todas como in_progress
|
|
1018
|
-
TaskUpdate({ taskId: planATask.id, status: "in_progress" })
|
|
1019
|
-
TaskUpdate({ taskId: planBTask.id, status: "in_progress" })
|
|
1020
|
-
TaskUpdate({ taskId: planCTask.id, status: "in_progress" })
|
|
1021
|
-
|
|
1022
|
-
// 3. Lanzar agentes EN UN SOLO MENSAJE
|
|
1023
|
-
Task(elsabro-executor) Plan A |
|
|
1024
|
-
Task(elsabro-executor) Plan B |
|
|
1025
|
-
Task(elsabro-executor) Plan C
|
|
1026
|
-
|
|
1027
|
-
// 4. Al completar cada uno
|
|
1028
|
-
TaskUpdate({ taskId: planATask.id, status: "completed" })
|
|
1029
|
-
// ...
|
|
1030
|
-
```
|
|
1031
|
-
|
|
1032
|
-
### Visualización automática (Ctrl+T)
|
|
1033
|
-
```
|
|
1034
|
-
📋 Execute Phase 3:
|
|
1035
|
-
✅ Wave 1 - Completed (3/3 plans)
|
|
1036
|
-
🔧 Wave 2 - Executing Plan D... (1/2 plans done)
|
|
1037
|
-
✅ Plan D - Completed
|
|
1038
|
-
⏳ Plan E - In Progress
|
|
1039
|
-
⏳ Wave 3 - Blocked by Wave 2
|
|
1040
|
-
⏳ Verification - Blocked by Wave 3
|
|
1041
|
-
```
|
|
1042
|
-
|
|
1043
|
-
### Cuándo NO paralelizar
|
|
1044
|
-
- Planes con dependencias entre sí (usar `blockedBy`)
|
|
1045
|
-
- Plan 2 necesita output de Plan 1
|
|
1046
|
-
- Modifican los mismos archivos
|
|
1047
|
-
|
|
1048
|
-
### Expresar dependencias entre planes
|
|
1049
|
-
```javascript
|
|
1050
|
-
// Plan B depende de Plan A
|
|
1051
|
-
TaskUpdate({
|
|
1052
|
-
taskId: "plan-B-id",
|
|
1053
|
-
addBlockedBy: ["plan-A-id"]
|
|
1054
|
-
})
|
|
1055
|
-
// Plan B no puede empezar hasta que Plan A complete
|
|
1056
|
-
```
|
|
1057
|
-
</parallel_execution>
|
|
1058
|
-
|
|
1059
|
-
<worktrees_integration>
|
|
1060
|
-
## Integración con Worktrees Paralelos
|
|
1061
|
-
|
|
1062
|
-
**IMPORTAR**: En waves con múltiples agentes, usar worktrees para aislamiento.
|
|
1063
|
-
|
|
1064
|
-
### Cuándo Usar Worktrees
|
|
1065
|
-
|
|
1066
|
-
- Profile "careful": SIEMPRE usar worktrees
|
|
1067
|
-
- Más de 2 agentes en wave: Considerar worktrees
|
|
1068
|
-
- Archivos compartidos entre agentes: OBLIGATORIO usar worktrees
|
|
1069
|
-
|
|
1070
|
-
### Flujo con Worktrees
|
|
1071
|
-
|
|
1072
|
-
```javascript
|
|
1073
|
-
// Antes de ejecutar wave paralela
|
|
1074
|
-
if (shouldUseWorktrees(wave, profile)) {
|
|
1075
|
-
const agents = wave.plans.map(p => p.agent);
|
|
1076
|
-
|
|
1077
|
-
// Crear worktrees
|
|
1078
|
-
Bash(`./scripts/setup-parallel-worktrees.sh create ${agents.join(' ')}`);
|
|
1079
|
-
|
|
1080
|
-
// OBLIGATORIO: Crear Agent Team para worktree paralelo (Rule 8)
|
|
1081
|
-
TeamCreate({
|
|
1082
|
-
team_name: "elsabro-worktree",
|
|
1083
|
-
description: "Parallel worktree execution for wave " + wave.id
|
|
1084
|
-
})
|
|
1085
|
-
|
|
1086
|
-
// Ejecutar agentes como teammates en sus worktrees
|
|
1087
|
-
for (let i = 0; i < agents.length; i++) {
|
|
1088
|
-
Task({
|
|
1089
|
-
subagent_type: agents[i],
|
|
1090
|
-
team_name: "elsabro-worktree",
|
|
1091
|
-
name: `wt-agent-${i + 1}`,
|
|
1092
|
-
prompt: `Trabaja en worktree: ../elsabro-worktrees/${agents[i]}-wt/`
|
|
1093
|
-
});
|
|
1094
|
-
}
|
|
1095
|
-
|
|
1096
|
-
// Shutdown teammates y cleanup team
|
|
1097
|
-
for (let i = 0; i < agents.length; i++) {
|
|
1098
|
-
SendMessage({
|
|
1099
|
-
type: "shutdown_request",
|
|
1100
|
-
recipient: `wt-agent-${i + 1}`,
|
|
1101
|
-
content: "Worktree work complete"
|
|
1102
|
-
});
|
|
1103
|
-
}
|
|
1104
|
-
TeamDelete();
|
|
1105
|
-
|
|
1106
|
-
// Merge y cleanup worktrees al completar
|
|
1107
|
-
Bash(`./scripts/setup-parallel-worktrees.sh complete ${agents.join(' ')}`);
|
|
1108
|
-
}
|
|
1109
|
-
```
|
|
1110
|
-
|
|
1111
|
-
### Resolución de Conflictos
|
|
1112
|
-
|
|
1113
|
-
Si hay conflictos en el merge:
|
|
1114
|
-
1. Pausar ejecución
|
|
1115
|
-
2. Mostrar conflictos al usuario
|
|
1116
|
-
3. Opciones: resolver manual, descartar branch, o abortar
|
|
1117
|
-
</worktrees_integration>
|
|
1118
|
-
|
|
1119
|
-
<error_handling>
|
|
1120
|
-
## Manejo de Errores en Ejecucion Paralela
|
|
1121
|
-
|
|
1122
|
-
**IMPORTAR**: Este comando DEBE seguir `/references/error-contracts.md`.
|
|
1123
|
-
|
|
1124
|
-
### Inicializacion con Contratos
|
|
1125
|
-
|
|
1126
|
-
```javascript
|
|
1127
|
-
// Antes de cualquier wave, inicializar contratos
|
|
1128
|
-
const registryValidator = new ContractRegistryValidator();
|
|
1129
|
-
const sessionValidator = new ContractSessionValidator();
|
|
1130
|
-
const timeoutHandler = new ContractTimeoutHandler();
|
|
1131
|
-
const retryPolicy = new ContractRetryPolicy({
|
|
1132
|
-
maxAttempts: 3,
|
|
1133
|
-
baseDelayMs: 1000,
|
|
1134
|
-
backoffMultiplier: 2
|
|
1135
|
-
});
|
|
1136
|
-
const errorAggregator = new ContractErrorAggregator("quorum");
|
|
1137
|
-
const severityClassifier = new ContractSeverityClassifier();
|
|
1138
|
-
|
|
1139
|
-
// 1. Validar registry
|
|
1140
|
-
const agentsNeeded = dispatcher.exploration.agents;
|
|
1141
|
-
const batch = await registryValidator.validateBatch(agentsNeeded);
|
|
1142
|
-
if (!batch.canProceed) {
|
|
1143
|
-
return handleCriticalError("REGISTRY_MISSING", batch.details);
|
|
1144
|
-
}
|
|
1145
|
-
|
|
1146
|
-
// 2. Validar sesion
|
|
1147
|
-
const session = await sessionValidator.load();
|
|
1148
|
-
if (!session.success) {
|
|
1149
|
-
return handleCriticalError("SESSION_INVALID", session);
|
|
1150
|
-
}
|
|
1151
|
-
```
|
|
55
|
+
Capturar el output JSON. Parsear `instruction` del resultado.
|
|
1152
56
|
|
|
1153
|
-
|
|
57
|
+
2. **CHECK**: Si `finished: true` -> ir a seccion 5. Si `error` -> mostrar al usuario, ofrecer retry/abort.
|
|
1154
58
|
|
|
1155
|
-
|
|
1156
|
-
```javascript
|
|
1157
|
-
// Policy: continue_all (exploracion es best-effort)
|
|
1158
|
-
errorAggregator.setPolicy("continue_all");
|
|
1159
|
-
|
|
1160
|
-
const results = await Promise.all([
|
|
1161
|
-
executeWithRetry("explore-1", () => Task(Explore)),
|
|
1162
|
-
executeWithRetry("explore-2", () => Task(CodeExplorer)),
|
|
1163
|
-
executeWithRetry("explore-3", () => Task(Plan))
|
|
1164
|
-
]);
|
|
1165
|
-
|
|
1166
|
-
const summary = await errorAggregator.aggregate("exploration", results);
|
|
1167
|
-
// continue_all: siempre continua, reporta al final
|
|
1168
|
-
```
|
|
1169
|
-
|
|
1170
|
-
#### Fase Implementacion (OPUS x2 por wave)
|
|
1171
|
-
```javascript
|
|
1172
|
-
// Policy: quorum (>50% debe tener exito)
|
|
1173
|
-
errorAggregator.setPolicy("quorum");
|
|
1174
|
-
|
|
1175
|
-
for (const wave of waves) {
|
|
1176
|
-
timeoutHandler.startTimeout(wave.id, 60 * 60 * 1000); // 60min por wave
|
|
1177
|
-
|
|
1178
|
-
// OBLIGATORIO: Crear Agent Team para wave de implementacion (Rule 8)
|
|
1179
|
-
TeamCreate({
|
|
1180
|
-
team_name: "elsabro-wave-impl",
|
|
1181
|
-
description: "Implementation wave " + wave.id
|
|
1182
|
-
})
|
|
1183
|
-
|
|
1184
|
-
const results = await Promise.all(
|
|
1185
|
-
wave.plans.map((plan, i) =>
|
|
1186
|
-
executeWithRetry(plan.id, () => Task({
|
|
1187
|
-
subagent_type: "elsabro-executor",
|
|
1188
|
-
team_name: "elsabro-wave-impl",
|
|
1189
|
-
name: `wave-executor-${i + 1}`,
|
|
1190
|
-
prompt: plan
|
|
1191
|
-
}))
|
|
1192
|
-
)
|
|
1193
|
-
);
|
|
1194
|
-
|
|
1195
|
-
// Shutdown teammates y cleanup team
|
|
1196
|
-
wave.plans.forEach((_, i) => {
|
|
1197
|
-
SendMessage({
|
|
1198
|
-
type: "shutdown_request",
|
|
1199
|
-
recipient: `wave-executor-${i + 1}`,
|
|
1200
|
-
content: "Wave complete"
|
|
1201
|
-
});
|
|
1202
|
-
});
|
|
1203
|
-
TeamDelete();
|
|
1204
|
-
|
|
1205
|
-
const summary = await errorAggregator.aggregate(wave.id, results);
|
|
1206
|
-
|
|
1207
|
-
if (summary.decision === "STOP") {
|
|
1208
|
-
// Quorum no alcanzado
|
|
1209
|
-
await notifyUserImmediately({
|
|
1210
|
-
severity: "CRITICAL",
|
|
1211
|
-
message: `Wave ${wave.id} fallo: ${summary.reason}`,
|
|
1212
|
-
options: ["retry", "debug", "abort"]
|
|
1213
|
-
});
|
|
1214
|
-
return;
|
|
1215
|
-
}
|
|
1216
|
-
|
|
1217
|
-
timeoutHandler.completeTimeout(wave.id);
|
|
1218
|
-
}
|
|
1219
|
-
```
|
|
1220
|
-
|
|
1221
|
-
#### Fase Verificacion (OPUS x3)
|
|
1222
|
-
```javascript
|
|
1223
|
-
// Policy: fail_fast (verificacion debe pasar completa)
|
|
1224
|
-
errorAggregator.setPolicy("fail_fast");
|
|
1225
|
-
|
|
1226
|
-
const verificationResults = await Promise.all([
|
|
1227
|
-
executeWithRetry("verify-code", () => Task(CodeReviewer)),
|
|
1228
|
-
executeWithRetry("verify-silent", () => Task(SilentFailureHunter)),
|
|
1229
|
-
executeWithRetry("verify-tests", () => Task(TestAnalyzer))
|
|
1230
|
-
]);
|
|
1231
|
-
|
|
1232
|
-
const summary = await errorAggregator.aggregate("verification", verificationResults);
|
|
1233
|
-
|
|
1234
|
-
if (summary.decision === "STOP") {
|
|
1235
|
-
// Cualquier fallo en verificacion es critico
|
|
1236
|
-
await displayVerificationFailure(summary);
|
|
1237
|
-
return;
|
|
1238
|
-
}
|
|
1239
|
-
```
|
|
1240
|
-
|
|
1241
|
-
### Escalamiento de Errores
|
|
1242
|
-
|
|
1243
|
-
```
|
|
1244
|
-
┌─────────────────────────────────────────────────────────────────────┐
|
|
1245
|
-
│ ESCALAMIENTO DE ERRORES │
|
|
1246
|
-
├─────────────────────────────────────────────────────────────────────┤
|
|
1247
|
-
│ │
|
|
1248
|
-
│ Error detectado │
|
|
1249
|
-
│ ↓ │
|
|
1250
|
-
│ SeverityClassifier.classify(error) │
|
|
1251
|
-
│ ↓ │
|
|
1252
|
-
│ ┌─────────────────────────────────────────────────────────────┐ │
|
|
1253
|
-
│ │ CRITICAL: Notificar inmediatamente, STOP │ │
|
|
1254
|
-
│ │ HIGH: Notificar, ofrecer opciones [fix/debug/abort] │ │
|
|
1255
|
-
│ │ MEDIUM: Agregar a resumen, continuar │ │
|
|
1256
|
-
│ │ LOW: Log para debugging, continuar │ │
|
|
1257
|
-
│ └─────────────────────────────────────────────────────────────┘ │
|
|
1258
|
-
│ │
|
|
1259
|
-
└─────────────────────────────────────────────────────────────────────┘
|
|
1260
|
-
```
|
|
59
|
+
3. **DISPATCH**: Ejecutar segun `instruction.type` (ver seccion 3). Guardar el resultado.
|
|
1261
60
|
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
```javascript
|
|
1265
|
-
async function executeWithRetry(operationId, operation) {
|
|
1266
|
-
return await retryPolicy.executeWithRetry(
|
|
1267
|
-
operationId,
|
|
1268
|
-
operation,
|
|
1269
|
-
{
|
|
1270
|
-
onAttempt: (attempt) => {
|
|
1271
|
-
console.log(`[RETRY] ${operationId}: Intento ${attempt}/3`);
|
|
1272
|
-
},
|
|
1273
|
-
onSuccess: (result, attempts) => {
|
|
1274
|
-
if (attempts > 1) {
|
|
1275
|
-
console.log(`[RECOVERED] ${operationId}: Exitoso en intento ${attempts}`);
|
|
1276
|
-
}
|
|
1277
|
-
},
|
|
1278
|
-
onFailure: (error, attempts) => {
|
|
1279
|
-
console.error(`[FAILED] ${operationId}: Fallo despues de ${attempts} intentos`);
|
|
1280
|
-
|
|
1281
|
-
// Clasificar para decidir siguiente accion
|
|
1282
|
-
const classification = severityClassifier.classify(error.message);
|
|
1283
|
-
if (classification.severity === "CRITICAL") {
|
|
1284
|
-
throw new CriticalError(error, classification);
|
|
1285
|
-
}
|
|
1286
|
-
}
|
|
1287
|
-
}
|
|
1288
|
-
);
|
|
1289
|
-
}
|
|
1290
|
-
```
|
|
1291
|
-
|
|
1292
|
-
### Guardar Estado de Errores
|
|
1293
|
-
|
|
1294
|
-
Al completar cada wave (exito o fallo):
|
|
1295
|
-
|
|
1296
|
-
```javascript
|
|
1297
|
-
// Actualizar state.json con errores para recovery
|
|
1298
|
-
state.errors = {
|
|
1299
|
-
count: allErrors.length,
|
|
1300
|
-
lastError: allErrors[allErrors.length - 1],
|
|
1301
|
-
byWave: errorsByWave,
|
|
1302
|
-
bySeverity: {
|
|
1303
|
-
CRITICAL: criticalErrors,
|
|
1304
|
-
HIGH: highErrors,
|
|
1305
|
-
MEDIUM: mediumErrors,
|
|
1306
|
-
LOW: lowErrors
|
|
1307
|
-
}
|
|
1308
|
-
};
|
|
1309
|
-
|
|
1310
|
-
state.parallelExecution = {
|
|
1311
|
-
policy: currentPolicy,
|
|
1312
|
-
activeAgents: [],
|
|
1313
|
-
completedAgents: completedAgentIds,
|
|
1314
|
-
failedAgents: failedAgentIds
|
|
1315
|
-
};
|
|
1316
|
-
|
|
1317
|
-
await sessionValidator.save(state);
|
|
1318
|
-
```
|
|
1319
|
-
|
|
1320
|
-
### Clasificacion de Errores (Referencia Rapida)
|
|
1321
|
-
|
|
1322
|
-
| Severity | Emoji | Accion |
|
|
1323
|
-
|----------|-------|--------|
|
|
1324
|
-
| CRITICAL | Parar | No puede continuar de ninguna forma |
|
|
1325
|
-
| HIGH | Preguntar | Ofrecer opciones: fix/debug/abort |
|
|
1326
|
-
| MEDIUM | Warning | Mostrar y continuar |
|
|
1327
|
-
| LOW | Info | Log y continuar |
|
|
1328
|
-
|
|
1329
|
-
### Reglas de Desviacion
|
|
1330
|
-
|
|
1331
|
-
| Situacion | Severity | Accion |
|
|
1332
|
-
|-----------|----------|--------|
|
|
1333
|
-
| Bug que impide continuar | HIGH | Auto-fix (3 intentos) |
|
|
1334
|
-
| Falta validacion critica | HIGH | Auto-add |
|
|
1335
|
-
| Falta dependencia | HIGH | Auto-install |
|
|
1336
|
-
| Cambio arquitectonico | HIGH | CHECKPOINT |
|
|
1337
|
-
| Tests fallan | HIGH | Auto-fix (5 intentos) |
|
|
1338
|
-
| Lint warnings | HIGH | Auto-fix (incluido en quality gate) |
|
|
1339
|
-
|
|
1340
|
-
### Actualizar Estado con Tasks
|
|
1341
|
-
|
|
1342
|
-
Despues de errores, actualizar tanto SESSION-STATE.json como Tasks:
|
|
1343
|
-
|
|
1344
|
-
```javascript
|
|
1345
|
-
// 1. Actualizar task con metadata de error
|
|
1346
|
-
TaskUpdate({
|
|
1347
|
-
taskId: "plan-X-id",
|
|
1348
|
-
metadata: {
|
|
1349
|
-
error: {
|
|
1350
|
-
code: "TESTS_FAILED",
|
|
1351
|
-
severity: "HIGH",
|
|
1352
|
-
at: "2024-01-20T15:25:00Z",
|
|
1353
|
-
attempt: 3,
|
|
1354
|
-
maxAttempts: 3
|
|
1355
|
-
}
|
|
1356
|
-
}
|
|
1357
|
-
})
|
|
1358
|
-
|
|
1359
|
-
// 2. Si retry exhausted, NO marcar completed
|
|
1360
|
-
// Crear subtask de fix
|
|
1361
|
-
TaskCreate({
|
|
1362
|
-
subject: "Fix: Tests failing in Plan X",
|
|
1363
|
-
description: "3 retry attempts exhausted, needs manual fix",
|
|
1364
|
-
activeForm: "Fixing test failures...",
|
|
1365
|
-
metadata: { type: "bugfix", parentPlan: "plan-X-id" }
|
|
1366
|
-
}) // → bugfix-id
|
|
1367
|
-
|
|
1368
|
-
// 3. Bloquear verificacion hasta que bugfix complete
|
|
1369
|
-
TaskUpdate({
|
|
1370
|
-
taskId: "verify-aggregate-id",
|
|
1371
|
-
addBlockedBy: ["bugfix-id"]
|
|
1372
|
-
})
|
|
1373
|
-
|
|
1374
|
-
// 4. Tambien actualizar SESSION-STATE.json para compatibilidad
|
|
1375
|
-
```
|
|
61
|
+
4. **OBSERVE**: Emitir senales de observabilidad (ver seccion 4).
|
|
1376
62
|
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
```javascript
|
|
1382
|
-
// Volver plan a in_progress (no crear nuevo)
|
|
1383
|
-
TaskUpdate({ taskId: "plan-X-id", status: "in_progress" })
|
|
1384
|
-
|
|
1385
|
-
// Re-ejecutar
|
|
1386
|
-
Task(elsabro-executor) para Plan X
|
|
1387
|
-
|
|
1388
|
-
// Marcar completed cuando funcione
|
|
1389
|
-
TaskUpdate({ taskId: "plan-X-id", status: "completed" })
|
|
1390
|
-
```
|
|
1391
|
-
|
|
1392
|
-
### Ver Estado Actual
|
|
1393
|
-
|
|
1394
|
-
```javascript
|
|
1395
|
-
// Listar todas las tasks
|
|
1396
|
-
TaskList()
|
|
1397
|
-
|
|
1398
|
-
// Ver detalles de una task especifica
|
|
1399
|
-
TaskGet({ taskId: "plan-X-id" })
|
|
1400
|
-
```
|
|
1401
|
-
</error_handling>
|
|
1402
|
-
|
|
1403
|
-
<summary_creation>
|
|
1404
|
-
## Creación de Summary
|
|
1405
|
-
|
|
1406
|
-
Al completar un plan:
|
|
1407
|
-
|
|
1408
|
-
```markdown
|
|
1409
|
-
# Summary: [Nombre del Plan]
|
|
1410
|
-
|
|
1411
|
-
## Completado
|
|
1412
|
-
- [x] Tarea 1
|
|
1413
|
-
- [x] Tarea 2
|
|
1414
|
-
|
|
1415
|
-
## Archivos
|
|
1416
|
-
- path/to/file.ts
|
|
1417
|
-
- path/to/another.ts
|
|
1418
|
-
|
|
1419
|
-
## Commits
|
|
1420
|
-
- abc1234: feat(01-01): [descripción]
|
|
1421
|
-
- def5678: feat(01-01): [descripción]
|
|
1422
|
-
|
|
1423
|
-
## Verificación
|
|
1424
|
-
- [x] Build: npm run build
|
|
1425
|
-
- [x] Tests: npm run test
|
|
1426
|
-
```
|
|
1427
|
-
</summary_creation>
|
|
1428
|
-
|
|
1429
|
-
<engine_integration>
|
|
1430
|
-
## Flow Engine (v7.0.0) + CLI
|
|
1431
|
-
|
|
1432
|
-
The flow engine runtime is at `flow-engine/src/index.js`.
|
|
1433
|
-
The CLI is at `flow-engine/src/cli.js` (also `npm run flow` or `elsabro-flow`).
|
|
1434
|
-
|
|
1435
|
-
### Quick Reference
|
|
1436
|
-
|
|
1437
|
-
```bash
|
|
1438
|
-
# Validate flow + see team compositions
|
|
1439
|
-
node flow-engine/src/cli.js validate --flow flows/development-flow.json
|
|
1440
|
-
|
|
1441
|
-
# Dry-run (full path, mock callbacks)
|
|
1442
|
-
node flow-engine/src/cli.js dry-run --flow flows/development-flow.json --task "feature" --profile default
|
|
1443
|
-
|
|
1444
|
-
# Step-based execution
|
|
1445
|
-
node flow-engine/src/cli.js init --flow flows/development-flow.json --task "build auth" --profile default
|
|
1446
|
-
node flow-engine/src/cli.js step --flow flows/development-flow.json
|
|
1447
|
-
node flow-engine/src/cli.js complete --flow flows/development-flow.json --result '{"output": "done"}'
|
|
1448
|
-
node flow-engine/src/cli.js status --flow flows/development-flow.json
|
|
1449
|
-
```
|
|
1450
|
-
</engine_integration>
|
|
1451
|
-
|
|
1452
|
-
<cli_driven_execution>
|
|
1453
|
-
## CLI-Driven Execution (v7.0.0)
|
|
1454
|
-
|
|
1455
|
-
The CLI manages graph traversal. It auto-resolves simple nodes (entry, condition, router, exit)
|
|
1456
|
-
and stops at actionable nodes, emitting a JSON instruction. Claude follows the instruction,
|
|
1457
|
-
then calls `complete` to advance.
|
|
1458
|
-
|
|
1459
|
-
### Main Loop
|
|
1460
|
-
|
|
1461
|
-
```
|
|
1462
|
-
init → [step → execute instruction → complete]* → step (finished)
|
|
1463
|
-
```
|
|
63
|
+
5. **COMPLETE**: Enviar resultado al CLI:
|
|
64
|
+
```bash
|
|
65
|
+
node flow-engine/src/cli.js complete --flow "$FLOW" --result '{"output": "..."}'
|
|
66
|
+
```
|
|
1464
67
|
|
|
1465
|
-
|
|
1466
|
-
2. **step**: Auto-resolves through conditions/routers, stops at actionable node, returns instruction JSON
|
|
1467
|
-
3. **execute instruction**: Claude executes based on instruction type (see below)
|
|
1468
|
-
4. **complete**: Stores result, advances checkpoint to next node
|
|
1469
|
-
5. Repeat step→execute→complete until `step` returns `{ finished: true }`
|
|
68
|
+
6. Volver al paso 1.
|
|
1470
69
|
|
|
1471
|
-
|
|
70
|
+
## 3. Dispatch por Tipo de Instruccion
|
|
1472
71
|
|
|
1473
|
-
|
|
72
|
+
### type: "agent"
|
|
1474
73
|
```javascript
|
|
1475
74
|
// instruction: { type: "agent", nodeId, agent, model, inputs }
|
|
1476
75
|
Task({
|
|
1477
76
|
subagent_type: instruction.agent,
|
|
1478
77
|
model: instruction.model,
|
|
1479
|
-
prompt:
|
|
78
|
+
prompt: JSON.stringify(instruction.inputs)
|
|
1480
79
|
})
|
|
80
|
+
// result: { output: agentOutput }
|
|
1481
81
|
```
|
|
1482
82
|
|
|
1483
|
-
|
|
83
|
+
### type: "parallel" con useAgentTeams: false
|
|
1484
84
|
```javascript
|
|
1485
85
|
// instruction: { type: "parallel", nodeId, useAgentTeams: false, branches }
|
|
1486
|
-
//
|
|
86
|
+
// Todos haiku -> subagents sueltos (excepcion Rule 8)
|
|
1487
87
|
for (const branch of instruction.branches) {
|
|
1488
|
-
Task({
|
|
1489
|
-
subagent_type: branch.agent,
|
|
1490
|
-
model: "haiku",
|
|
1491
|
-
prompt: `Execute: ${JSON.stringify(branch.inputs)}`
|
|
1492
|
-
})
|
|
88
|
+
Task({ subagent_type: branch.agent, model: "haiku", prompt: JSON.stringify(branch.inputs) })
|
|
1493
89
|
}
|
|
90
|
+
// result: branches.map(b => ({ id: b.id, output: branchOutput }))
|
|
1494
91
|
```
|
|
1495
92
|
|
|
1496
|
-
|
|
93
|
+
### type: "parallel" con useAgentTeams: true
|
|
1497
94
|
```javascript
|
|
1498
|
-
// instruction: { type: "parallel", nodeId, useAgentTeams: true, team
|
|
1499
|
-
//
|
|
1500
|
-
// The engine composed a team of 5+ members:
|
|
1501
|
-
// - Core branch agents (from flow definition)
|
|
1502
|
-
// - Support agents (verifier, qa, debugger, etc.) padded to minimum 5
|
|
1503
|
-
//
|
|
1504
|
-
// Claude Code handles team lifecycle automatically:
|
|
95
|
+
// instruction: { type: "parallel", nodeId, useAgentTeams: true, team, branches }
|
|
96
|
+
// El engine ya compuso team de 5+ miembros via callbacks.js
|
|
1505
97
|
|
|
1506
|
-
TeamCreate({
|
|
1507
|
-
team_name: instruction.team.name,
|
|
1508
|
-
description: instruction.team.description
|
|
1509
|
-
})
|
|
98
|
+
TeamCreate({ team_name: instruction.team.name, description: instruction.team.description })
|
|
1510
99
|
|
|
1511
|
-
// Launch ALL team members (not just branches — the full team of 5+)
|
|
1512
100
|
for (const member of instruction.team.members) {
|
|
1513
101
|
Task({
|
|
1514
102
|
subagent_type: member.agent,
|
|
1515
103
|
model: member.model,
|
|
1516
104
|
team_name: instruction.team.name,
|
|
1517
105
|
name: member.name,
|
|
1518
|
-
prompt: `Role: ${member.role}. Execute
|
|
106
|
+
prompt: `Role: ${member.role}. Execute: ${instruction.nodeId}`
|
|
1519
107
|
})
|
|
1520
108
|
}
|
|
1521
109
|
|
|
1522
|
-
//
|
|
110
|
+
// Al completar todos:
|
|
1523
111
|
for (const member of instruction.team.members) {
|
|
1524
112
|
SendMessage({ type: "shutdown_request", recipient: member.name, content: "Done" })
|
|
1525
113
|
}
|
|
1526
114
|
TeamDelete()
|
|
115
|
+
// result: team outputs aggregated
|
|
1527
116
|
```
|
|
1528
117
|
|
|
1529
|
-
|
|
118
|
+
### type: "interrupt"
|
|
1530
119
|
```javascript
|
|
1531
|
-
// instruction: { type: "interrupt", nodeId, display, routes
|
|
1532
|
-
AskUserQuestion({
|
|
1533
|
-
questions: [{
|
|
1534
|
-
question: instruction.display.title,
|
|
1535
|
-
options: instruction.display.options.map(o => ({ label: o.label, description: o.id }))
|
|
1536
|
-
}]
|
|
120
|
+
// instruction: { type: "interrupt", nodeId, display, routes }
|
|
121
|
+
const answer = AskUserQuestion({
|
|
122
|
+
questions: [{ question: instruction.display.title, options: instruction.display.options }]
|
|
1537
123
|
})
|
|
1538
|
-
//
|
|
124
|
+
// result: routeKey seleccionado por usuario (maps to instruction.routes)
|
|
1539
125
|
```
|
|
1540
126
|
|
|
1541
|
-
|
|
127
|
+
### type: "sequence"
|
|
1542
128
|
```javascript
|
|
1543
129
|
// instruction: { type: "sequence", nodeId, steps }
|
|
1544
130
|
for (const step of instruction.steps) {
|
|
1545
131
|
if (step.action === "bash") Bash(step.command)
|
|
1546
|
-
if (step.action === "agent") Task({ subagent_type: step.agent,
|
|
132
|
+
if (step.action === "agent") Task({ subagent_type: step.agent, prompt: step.inputs })
|
|
1547
133
|
if (step.action === "read_files") Read(step.files)
|
|
1548
134
|
}
|
|
135
|
+
// result: { steps: stepOutputs }
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## 4. Observabilidad (4 Senales)
|
|
139
|
+
|
|
140
|
+
Despues de cada `step` y `complete`, emitir al log:
|
|
141
|
+
|
|
1549
142
|
```
|
|
143
|
+
.elsabro/telemetry/execution-{flowId}.jsonl
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
| Senal | Cuando | Datos |
|
|
147
|
+
|---|---|---|
|
|
148
|
+
| `node_skip_counter` | step auto-resuelve N nodos | `{ signal: "node_skip", skipped: N, nodeId }` (NOTE: requires cli.js patch to include nodesVisited in step output) |
|
|
149
|
+
| `gate_bypass_detector` | step resuelve condition/router | `{ signal: "gate_check", nodeId, result: true/false }` |
|
|
150
|
+
| `execution_time_anomaly` | complete tarda >120s | `{ signal: "time_anomaly", nodeId, duration_ms }` |
|
|
151
|
+
| `diff_size_vs_review_ratio` | complete de parallel_review | `{ signal: "review_ratio", files, comments }` |
|
|
1550
152
|
|
|
1551
|
-
|
|
153
|
+
Formato: una linea JSON por evento (JSON Lines). Append-only.
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
echo '{"ts":"'$(date -u +%FT%TZ)'","signal":"node_skip","nodeId":"...","skipped":3}' >> .elsabro/telemetry/execution-${FLOW_ID}.jsonl
|
|
157
|
+
```
|
|
1552
158
|
|
|
1553
|
-
|
|
1554
|
-
|------|------|-------------------|-------|
|
|
1555
|
-
| `standard_analyze` | 4 haiku | NO TEAM (subagents) | 4 subagents |
|
|
1556
|
-
| `parallel_implementation` | executor, qa | + verifier, analyst, debugger | 5 |
|
|
1557
|
-
| `fix_issues` | debugger, error-detective, refactor | + verifier, qa | 5 |
|
|
1558
|
-
| `parallel_review` | code-reviewer, silent-failure, staff | + verifier, qa | 5 |
|
|
159
|
+
## 5. Finalizar
|
|
1559
160
|
|
|
1560
|
-
|
|
161
|
+
Cuando el loop retorna `{ finished: true }`:
|
|
1561
162
|
|
|
1562
|
-
1.
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
163
|
+
1. Actualizar `.elsabro/state.json` siguiendo @references/state-sync.md:
|
|
164
|
+
- Agregar a `history`
|
|
165
|
+
- Pasar `context.changed_files`, `context.commits`, `context.tests_added` para verify-work
|
|
166
|
+
- Limpiar `current_flow`
|
|
167
|
+
- Establecer `suggested_next: "verify-work"`
|
|
168
|
+
2. Actualizar `.elsabro/context.md` con resumen legible
|
|
169
|
+
|
|
170
|
+
## 6. Siguiente Paso
|
|
171
|
+
|
|
172
|
+
**Gate checks** (por referencia a @references/enforcement-rules.md):
|
|
173
|
+
- Rule 7: Si se escribio codigo -> code review debe haber pasado (el flow lo garantiza via parallel_review)
|
|
174
|
+
- Rule 8: Si se usaron 2+ agentes -> Agent Teams debe haberse usado (callbacks.js lo garantiza)
|
|
175
|
+
|
|
176
|
+
```
|
|
177
|
+
Siguiente Paso
|
|
178
|
+
|
|
179
|
+
-> /elsabro:verify-work -- verificar el trabajo completado
|
|
180
|
+
-> /elsabro:progress -- ver el progreso general del proyecto
|
|
181
|
+
```
|