elsabro 7.2.0 → 7.3.1

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