elsabro 7.3.1 → 7.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,17 +1,18 @@
1
- # ELSABRO v7.1.0
1
+ # ELSABRO v7.4.0
2
2
 
3
- **Tu asistente AI para crear apps increibles** — Orquestacion de agentes con flow engine, checkpointing y ejecucion paralela.
3
+ **Tu asistente AI para crear apps increibles** — Orquestacion de agentes con flow engine, checkpointing, ejecucion paralela y skill auto-discovery.
4
4
 
5
- ELSABRO es un sistema de desarrollo AI-powered para Claude Code que te guia paso a paso en la creacion de aplicaciones. Incluye un flow engine con 44 nodos, 12 agentes especializados, un CLI para control de flujo, y un sistema de checkpoints para recuperacion automatica.
5
+ ELSABRO es un sistema de desarrollo AI-powered para Claude Code que te guia paso a paso en la creacion de aplicaciones. Incluye un flow engine con 47 nodos, 12 agentes especializados, un CLI para control de flujo, un sistema de checkpoints para recuperacion automatica, y un pipeline completo de skill discovery e invocacion.
6
6
 
7
- ## Que Hay de Nuevo en v7.1.0
7
+ ## Que Hay de Nuevo en v7.4
8
8
 
9
- - **Flow Engine Runtime** — Motor de ejecucion basado en grafos con 9 tipos de nodos, resolución de templates, y checkpointing automatico
10
- - **CLI de 6 comandos** — validate, dry-run, init, step, complete, status
11
- - **PartyEngine** — Discusiones multi-agente con seleccion automatica de participantes
12
- - **CallbackProtocol** — Composicion automatica de Agent Teams (minimo 5 miembros)
13
- - **279 tests** — Zero dependencias externas, Node 18+
14
- - **Design-UI Routing** — Integracion con Stitch AI para generar pantallas desde texto
9
+ - **Skill Invocation Protocol** — Los agentes reciben `availableSkills` en sus inputs y siguen prioridad: skills instalados > recomendados > implementacion manual
10
+ - **Skill Auto-Install Flow** — 2 nodos nuevos descubren top 5 skills relevantes, preguntan al usuario, y batch-instalan en paralelo
11
+ - **Review Gate Enforcement** — Hooks reales en Claude Code bloquean git commit/push si hay codigo sin code review
12
+ - **Auto-Sync Validation** — Hook que valida 6 archivos criticos despues de cada implementacion con modo `--fix`
13
+ - **Agent Teams Cleanup** — Verificacion con 30s timeout antes de TeamDelete, telemetria de anomalias
14
+ - **Context7 Integration** — Consulta silenciosa de documentacion antes de tocar codigo con librerias externas
15
+ - **399 tests** — Zero dependencias externas, Node 18+
15
16
 
16
17
  ## Para Quien es ELSABRO?
17
18
 
@@ -110,13 +111,13 @@ ELSABRO incluye un motor de ejecucion de flujos basado en grafos. El engine es u
110
111
  ### Arquitectura
111
112
 
112
113
  ```
113
- JSON Flow Definition (44 nodos)
114
+ JSON Flow Definition (47 nodos)
114
115
  |
115
116
  v
116
117
  graph.js — Construye Map + valida referencias
117
118
  |
118
119
  v
119
- runner.js — While-loop: nodo executor checkpoint siguiente
120
+ runner.js — While-loop: nodo -> executor -> checkpoint -> siguiente
120
121
  |
121
122
  v
122
123
  executors.js — 9 tipos de nodos (entry, exit, condition, router,
@@ -127,9 +128,9 @@ JSON Flow Definition (44 nodos)
127
128
  (inyectados en runtime, el engine no sabe de Claude Code)
128
129
  ```
129
130
 
130
- - **279 tests**, 75 suites, 0 dependencias externas
131
+ - **399 tests**, 92 suites, 0 dependencias externas
131
132
  - **Checkpoint despues de cada nodo** — recuperacion automatica desde cualquier punto
132
- - **Template resolver** — 7 tipos de expresiones `{{...}}` sin `eval()`
133
+ - **Template resolver** — 7 tipos de expresiones sin code execution
133
134
 
134
135
  Para mas detalles ver [ARCHITECTURE.md](ARCHITECTURE.md).
135
136
 
@@ -154,9 +155,52 @@ node flow-engine/src/cli.js status --flow flows/development-flow.json
154
155
  ### Flow Definitions
155
156
 
156
157
  ELSABRO incluye 2 flow definitions:
157
- - `flows/development-flow.json` — Flujo completo de desarrollo (44 nodos, ~1080 lineas)
158
+ - `flows/development-flow.json` — Flujo completo de desarrollo (47 nodos, ~1200 lineas)
158
159
  - `flows/quick-flow.json` — Flujo rapido para tareas simples (8 nodos)
159
160
 
161
+ ## Hooks System
162
+
163
+ ELSABRO incluye hooks automaticos que se integran con Claude Code:
164
+
165
+ | Hook | Evento | Funcion |
166
+ |------|--------|---------|
167
+ | `review-gate.sh` | PostToolUse (Write/Edit) | Bloquea git commit si hay codigo sin code review |
168
+ | `auto-sync-check.sh` | PostCommand | Valida sincronizacion de 6 archivos criticos |
169
+ | `check-review-skills.sh` | Pre-review | Verifica que skills de review estan instalados |
170
+ | `skill-discovery.sh` | PreFlow | Descubre y recomienda skills relevantes |
171
+
172
+ ### Review Gate
173
+
174
+ Cada vez que se modifica codigo, el review gate se activa automaticamente:
175
+ ```
176
+ Write/Edit -> flag set -> code review -> fix issues -> repeat until clean -> flag clear -> commit allowed
177
+ ```
178
+
179
+ ### Auto-Sync Validation
180
+
181
+ Valida que archivos criticos esten sincronizados:
182
+ ```bash
183
+ # Verificar sincronizacion
184
+ bash hooks/auto-sync-check.sh
185
+
186
+ # Auto-corregir desyncs simples
187
+ bash hooks/auto-sync-check.sh --fix
188
+ ```
189
+
190
+ ## Skill Discovery
191
+
192
+ ELSABRO descubre automaticamente skills relevantes antes de cada ejecucion:
193
+
194
+ 1. **Descubrimiento** — Escanea skills instalados (`~/.claude/skills/`), skills ELSABRO (`./skills/`), y el registry externo
195
+ 2. **Ranking** — Ordena por relevancia usando keyword matching con pesos
196
+ 3. **Presentacion** — Muestra top 5 al usuario con opcion de instalar
197
+ 4. **Inyeccion** — Skills disponibles se pasan como `availableSkills` a todos los agentes
198
+
199
+ Los agentes siguen el **Skill Invocation Protocol** (seccion 3.1 de execute.md):
200
+ - Prioridad: skills instalados > recomendados > implementacion manual
201
+ - Context7 se consulta silenciosamente para documentacion de librerias externas
202
+ - Skills que fallan no bloquean la ejecucion
203
+
160
204
  ## Agentes Especializados
161
205
 
162
206
  12 agentes con personalidades distintas, basados en BMAD-METHOD:
@@ -176,6 +220,8 @@ ELSABRO incluye 2 flow definitions:
176
220
  | `elsabro-quick-dev` | Barry | Desarrollo rapido con minima ceremonia |
177
221
  | `elsabro-yolo-dev` | Flash | Desarrollo ultra-rapido, maximo riesgo |
178
222
 
223
+ Cada agente tiene una seccion `<skills_usage>` personalizada que define que tipos de skills debe buscar y como usarlos segun su rol.
224
+
179
225
  ## PartyEngine
180
226
 
181
227
  Sistema de discusion multi-agente. Selecciona 2-3 agentes relevantes para un tema y ejecuta rondas de debate con sintesis automatica.
@@ -193,6 +239,9 @@ El engine usa un mapa de relevancia (18 categorias de keywords) para elegir los
193
239
  | `default` | Balance entre velocidad y seguridad |
194
240
  | `yolo` | Maximo velocidad, minima ceremonia |
195
241
  | `careful` | Maximo seguridad, verificacion exhaustiva |
242
+ | `teams` | Agent Teams con coordinacion peer-to-peer |
243
+ | `persistent-teams` | Persistent mode + Agent Teams + blocking review |
244
+ | `bmad` | Spec-Driven Development con PRD y Solution Design |
196
245
 
197
246
  Cambiar perfil:
198
247
  ```
@@ -202,10 +251,10 @@ Cambiar perfil:
202
251
  ## Como Funciona
203
252
 
204
253
  ```
205
- 1. Describes tu idea ELSABRO analiza y pregunta
206
- 2. Planifica las fases Crea planes atomicos con TDD
207
- 3. Ejecuta con agentes Parallel execution + checkpointing
208
- 4. Verifica automaticamente 3 reviewers + quality gates
254
+ 1. Describes tu idea -> ELSABRO analiza y pregunta
255
+ 2. Planifica las fases -> Crea planes atomicos con TDD
256
+ 3. Ejecuta con agentes -> Parallel execution + checkpointing
257
+ 4. Verifica automaticamente -> 3 reviewers + quality gates
209
258
  ```
210
259
 
211
260
  Persistent mode mantiene ELSABRO activo entre mensajes — escribe naturalmente y ELSABRO rutea al comando correcto.
@@ -226,12 +275,18 @@ Persistent mode mantiene ELSABRO activo entre mensajes — escribe naturalmente
226
275
  flow-engine/
227
276
  src/ — 9 modulos del engine (index, graph, template,
228
277
  executors, runner, checkpoint, callbacks, cli, party)
229
- tests/ — 9 archivos de tests (279 tests, 75 suites)
278
+ tests/ — 10 archivos de tests (399 tests, 92 suites)
230
279
  src/agent-cards.json — 9 personalidades de agentes
231
280
 
232
281
  flows/
233
- development-flow.json — Flujo completo (44 nodos)
282
+ development-flow.json — Flujo completo (47 nodos)
234
283
  quick-flow.json — Flujo rapido (8 nodos)
284
+
285
+ hooks/
286
+ review-gate.sh — Review gate (set/check/clear/status)
287
+ auto-sync-check.sh — Validacion de sincronizacion
288
+ check-review-skills.sh — Verificacion de skills de review
289
+ skill-discovery.sh — Discovery de skills pre-flow
235
290
  ```
236
291
 
237
292
  ## Actualizacion
@@ -283,6 +338,10 @@ rm -rf .elsabro .planning
283
338
 
284
339
  | Version | Milestone | Cambio Principal |
285
340
  |---------|-----------|-----------------|
341
+ | 7.4.0 | M7+ | Skill invocation protocol, review gate enforcement, auto-sync hook, 47 nodos, 399 tests |
342
+ | 7.3.2 | M7 | Validation errors/warnings separation, case-insensitive hasCriticalIssues |
343
+ | 7.3.1 | M7 | PR #1: 23 critical fixes, skill auto-install hooks, deprecated teams bypass |
344
+ | 7.3.0 | M7 | Execute.md reescrito (-89%), observabilidad JSONL, limpieza codigo fantasma |
286
345
  | 7.1.0 | M5 + M6 | AT compliance, design-ui routing, 279 failure mode tests |
287
346
  | 7.0.0 | M4 | Feature completeness — 42/42 nodos, CLI, 257 tests |
288
347
  | 6.0.0 | M3 | Flow engine runtime — 6 source files, 109 tests |
@@ -94,6 +94,38 @@ CHECKPOINT (preguntar):
94
94
  - payments/stripe → skills/payments-setup.md
95
95
  </skill_awareness>
96
96
 
97
+ <skills_usage>
98
+ ## Uso de Skills en Implementacion
99
+
100
+ ### Deteccion Automatica de Skills
101
+ Cuando `availableSkills` esta presente en los inputs del contexto:
102
+ 1. **Escanear tech stack** — Identificar frameworks, lenguajes y librerias del plan
103
+ 2. **Matchear con skills disponibles** — Buscar skills que cubran el stack detectado
104
+ 3. **Priorizar skill especializado > implementacion manual** — Si existe un skill verificado, usarlo
105
+
106
+ ### Skills Prioritarios para Executor
107
+ | Tech Stack | Skill Recomendado | Uso |
108
+ |------------|-------------------|-----|
109
+ | React Native | react-native-best-practices | Patrones de componentes, navegacion, performance |
110
+ | Supabase/Postgres | supabase-postgres-best-practices | Queries, RLS, migrations, edge functions |
111
+ | TypeScript | typescript-pro | Tipos avanzados, generics, utility types |
112
+ | JavaScript | javascript-pro | Patrones modernos, async patterns |
113
+ | APIs REST | api-designer | Endpoints, validacion, error handling |
114
+
115
+ ### Context7 Obligatorio
116
+ **ANTES de tocar codigo de librerias externas**, consultar Context7 silenciosamente:
117
+ - Buscar documentacion actualizada del paquete
118
+ - Verificar API signatures y breaking changes
119
+ - No mostrar la consulta al usuario, solo aplicar el conocimiento
120
+
121
+ ### Reportar Skills Usados
122
+ En cada output de tarea completada, incluir:
123
+ ```
124
+ Skills aplicados: [nombre-skill-1], [nombre-skill-2]
125
+ Patrones usados: [patron-del-skill aplicado]
126
+ ```
127
+ </skills_usage>
128
+
97
129
  <execution_flow>
98
130
  ## Flujo de Ejecución
99
131
 
@@ -38,6 +38,45 @@ Soy **Quantum**, el orquestador de ejecución paralela. Como un director de orqu
38
38
  5. **Reportar en tiempo real** - El usuario sabe qué está pasando
39
39
  </principles>
40
40
 
41
+ <skills_usage>
42
+ ## Uso de Skills en Orquestacion
43
+
44
+ ### Deteccion y Distribucion de Skills
45
+ Cuando `availableSkills` esta presente en los inputs del contexto:
46
+ 1. **Inventariar skills disponibles** — Listar todos los skills relevantes para la tarea
47
+ 2. **Matchear skills con teammates** — Asignar skills especializados a cada agente
48
+ 3. **Distribuir en el prompt de spawn** — Incluir skills relevantes al lanzar cada teammate
49
+
50
+ ### Skills Prioritarios para Orchestrator
51
+ | Area | Skill Recomendado | Uso |
52
+ |------|-------------------|-----|
53
+ | Debugging paralelo | parallel-debugging | Coordinar multiples debuggers simultaneos |
54
+ | Task management | task-coordination-strategies | Dependencias, prioridades, conflict resolution |
55
+ | Team comms | team-communication-protocols | Patrones de comunicacion entre teammates |
56
+ | Architecture | architecture-designer | Decisiones de splitting y paralelizacion |
57
+
58
+ ### Distribucion de Skills a Teammates
59
+ Al crear un team o lanzar agentes, recomendar skills por rol:
60
+ - **executor teammates** → react-native-best-practices, supabase-postgres, typescript-pro
61
+ - **qa teammates** → playwright-expert, test-master, debugging-wizard
62
+ - **reviewer teammates** → code-reviewer, security-reviewer, secure-code-guardian
63
+ - **analyst teammates** → architecture-designer, database-optimizer
64
+
65
+ ### Tracking de Skills por Teammate
66
+ Durante la ejecucion paralela, registrar:
67
+ - Que skills uso cada teammate y en que tareas
68
+ - Si algun skill causo problemas o errores
69
+ - Efectividad del skill vs implementacion manual
70
+
71
+ ### Post-Mortem de Skills
72
+ Al generar el reporte final de ejecucion paralela, incluir:
73
+ ```
74
+ Skills distribuidos: [total]
75
+ Skills efectivos: [lista con resultado positivo]
76
+ Skills problematicos: [lista con issues encontrados]
77
+ ```
78
+ </skills_usage>
79
+
41
80
  <workflows>
42
81
  ## Workflows Disponibles
43
82
 
@@ -34,6 +34,43 @@ Soy **Murat**, Master Test Architect. Me especializo en API testing, backend ser
34
34
  7. **API tests are first-class citizens** - No solo UI
35
35
  </principles>
36
36
 
37
+ <skills_usage>
38
+ ## Uso de Skills en Testing y QA
39
+
40
+ ### Deteccion Automatica de Skills
41
+ Cuando `availableSkills` esta presente en los inputs del contexto:
42
+ 1. **Identificar framework de testing** — Jest, Vitest, Pytest, Playwright, etc.
43
+ 2. **Buscar skills de testing** — Matchear con skills disponibles para ese framework
44
+ 3. **Priorizar patrones del skill > patrones genericos** — Skills contienen best practices verificadas
45
+
46
+ ### Skills Prioritarios para QA
47
+ | Area | Skill Recomendado | Uso |
48
+ |------|-------------------|-----|
49
+ | E2E Browser | playwright-expert | Selectores, page objects, fixtures, paralelismo |
50
+ | Test Design | test-master | Estrategias de coverage, test doubles, TDD patterns |
51
+ | Debugging Tests | debugging-wizard | Diagnostico de flaky tests, race conditions |
52
+ | Security Testing | secure-code-guardian | OWASP testing, injection tests, auth bypass checks |
53
+
54
+ ### Consultar Skills para Patrones Especificos
55
+ Antes de escribir tests para un framework o libreria:
56
+ - Verificar si el skill tiene patrones de test recomendados
57
+ - Usar fixtures y helpers sugeridos por el skill
58
+ - Aplicar la estructura de archivos de test del skill
59
+
60
+ ### Integracion con CI/CD Skills
61
+ Cuando se configura pipeline de CI:
62
+ - Consultar devops-engineer para configuracion de stages
63
+ - Aplicar quality gates recomendados por el skill
64
+ - Configurar test reporters y coverage thresholds segun best practices
65
+
66
+ ### Reportar Skills Consultados
67
+ En cada test plan o suite generada, documentar:
68
+ ```
69
+ Skills consultados: [skill-1], [skill-2]
70
+ Patrones de testing aplicados: [patron-especifico]
71
+ ```
72
+ </skills_usage>
73
+
37
74
  <workflows>
38
75
  ## Workflows Disponibles
39
76
 
@@ -29,6 +29,43 @@ El executor puede decir "completado", pero debes verificar:
29
29
  4. ¿Hace lo que se pidió?
30
30
  </critical_rule>
31
31
 
32
+ <skills_usage>
33
+ ## Uso de Skills en Verificacion y Review
34
+
35
+ ### Deteccion Automatica de Skills
36
+ Cuando `availableSkills` esta presente en los inputs del contexto:
37
+ 1. **Identificar areas de review** — Calidad, seguridad, performance, tipos
38
+ 2. **Matchear con skills de review** — Buscar skills especializados para cada area
39
+ 3. **Priorizar skill de review especializado > checklist manual** — Skills profundizan mas
40
+
41
+ ### Skills Prioritarios para Verifier
42
+ | Area de Review | Skill Recomendado | Uso |
43
+ |----------------|-------------------|-----|
44
+ | Code Quality | code-reviewer | Naming, DRY, SOLID, complejidad ciclomatica |
45
+ | Security | security-reviewer | OWASP top 10, secrets exposure, auth flaws |
46
+ | Security Deep | secure-code-guardian | Injection, XSS, CSRF, dependency vulnerabilities |
47
+ | Architecture | architecture-designer | Patrones, separation of concerns, coupling |
48
+
49
+ ### Cross-Reference con Security Skills
50
+ Para verificacion de seguridad OWASP:
51
+ - Usar secure-code-guardian para analisis de vulnerabilidades
52
+ - Verificar contra checklist OWASP del skill
53
+ - Reportar findings con severidad clasificada por el skill
54
+
55
+ ### Verificacion Profunda con Skills
56
+ En Etapa 2 (Code Quality), si hay skills disponibles:
57
+ - Ejecutar analisis del skill ADEMAS del checklist standard
58
+ - El skill puede detectar anti-patterns especificos del framework
59
+ - Combinar findings del skill con findings manuales en reporte unificado
60
+
61
+ ### Reportar Skills Aplicados
62
+ En cada VERIFICATION.md generado, incluir:
63
+ ```
64
+ Skills de review usados: [skill-1], [skill-2]
65
+ Findings adicionales por skills: [cantidad]
66
+ ```
67
+ </skills_usage>
68
+
32
69
  <two_stage_review>
33
70
  ## Revisión de 2 Etapas
34
71
 
@@ -311,10 +311,39 @@ for (const member of instruction.team.members) {
311
311
  })
312
312
  }
313
313
 
314
- // Al completar todos:
314
+ // Al completar todos - shutdown con verificacion:
315
315
  for (const member of instruction.team.members) {
316
- SendMessage({ type: "shutdown_request", recipient: member.name, content: "Done" })
316
+ SendMessage({ type: "shutdown_request", recipient: member.name, content: "Task complete" })
317
317
  }
318
+
319
+ // Verificar que todos los teammates terminaron (max 30s timeout)
320
+ // Nota: sleep() es pseudocodigo. Implementar como: const sleep = ms => new Promise(r => setTimeout(r, ms));
321
+ const TEAM_SHUTDOWN_TIMEOUT = 30000;
322
+ const POLL_INTERVAL = 3000;
323
+ let elapsed = 0;
324
+ let allShutdown = false;
325
+
326
+ while (!allShutdown && elapsed < TEAM_SHUTDOWN_TIMEOUT) {
327
+ await sleep(POLL_INTERVAL); // ver nota arriba
328
+ elapsed += POLL_INTERVAL;
329
+ // Check if all members responded to shutdown
330
+ const teamStatus = TaskList(); // Check remaining active tasks
331
+ allShutdown = instruction.team.members.every(m =>
332
+ !teamStatus.some(t => t.owner === m.name && t.status === 'in_progress')
333
+ );
334
+ }
335
+
336
+ if (!allShutdown) {
337
+ // Emit telemetry for team lifecycle anomaly
338
+ emit_telemetry({
339
+ signal: "team_lifecycle_anomaly",
340
+ teamName: instruction.team.name,
341
+ timeout: TEAM_SHUTDOWN_TIMEOUT,
342
+ activeMembers: instruction.team.members.filter(m => /* still active */).map(m => m.name)
343
+ });
344
+ log_warn(`Team ${instruction.team.name}: ${elapsed}ms timeout - forcing cleanup`);
345
+ }
346
+
318
347
  TeamDelete()
319
348
  // result: team outputs aggregated
320
349
  ```
@@ -452,6 +481,41 @@ for (const step of instruction.steps) {
452
481
  // result: stepOutputs with all step execution results
453
482
  ```
454
483
 
484
+ ## 3.1. Skill Invocation Protocol
485
+
486
+ Cuando un agente recibe `availableSkills` en sus inputs, DEBE seguir este protocolo:
487
+
488
+ ### Prioridad de Uso
489
+ 1. **Skills instalados relevantes** — Usar primero los que ya estan instalados y matchean la tarea
490
+ 2. **Skills recomendados** — Si `recommendedSkills` incluye skills no instalados pero criticos, sugerir instalacion
491
+ 3. **Implementacion manual** — Solo si no hay skill apropiado disponible
492
+
493
+ ### Reglas
494
+ - **Top 5**: Solo considerar los 5 skills mas relevantes para la tarea actual
495
+ - **Silencioso**: No mostrar al usuario la consulta de skills - solo usarlos
496
+ - **Fallback**: Si un skill falla o no aplica, continuar con implementacion manual sin bloquear
497
+ - **Context7**: SIEMPRE consultar Context7 silenciosamente antes de tocar codigo que use librerias externas
498
+ - **Reportar**: Al final, incluir lista de skills usados en el output del agente
499
+
500
+ ### Context7 Integration
501
+ Antes de implementar codigo que use APIs externas:
502
+ 1. Resolver library ID: `mcp__context7__resolve-library-id` con el nombre de la libreria
503
+ 2. Consultar docs: `mcp__context7__query-docs` con la query relevante
504
+ 3. Aplicar patterns encontrados — si difieren de lo que se conoce, ALERTAR
505
+ 4. Todo esto es silencioso — el usuario no ve estas consultas
506
+
507
+ ### Telemetria
508
+ Emitir signal despues de cada agente que use skills:
509
+ ```json
510
+ {
511
+ "signal": "skill_usage",
512
+ "nodeId": "{{instruction.nodeId}}",
513
+ "skills_available": ["..."],
514
+ "skills_used": ["..."],
515
+ "skills_failed": ["..."]
516
+ }
517
+ ```
518
+
455
519
  ## 4. Observabilidad (4 Senales)
456
520
 
457
521
  Despues de cada `step` y `complete`, emitir al log:
@@ -66,11 +66,16 @@ function buildGraph(flowDefinition) {
66
66
  * Validate that all node references (next, routes, true, false, onMaxIterations,
67
67
  * onError) point to existing nodes, and detect orphaned nodes.
68
68
  *
69
+ * Returns errors (dangling references — fatal) and warnings (orphaned nodes —
70
+ * informational). Deprecated and standalone nodes are reported as warnings,
71
+ * not errors, since they are intentionally disconnected.
72
+ *
69
73
  * @param {{ nodes: Map<string, object>, entryNode: string }} graph
70
- * @returns {{ valid: boolean, errors: string[] }}
74
+ * @returns {{ valid: boolean, errors: string[], warnings: string[] }}
71
75
  */
72
76
  function validateGraph(graph) {
73
77
  const errors = [];
78
+ const warnings = [];
74
79
  const nodeIds = new Set(graph.nodes.keys());
75
80
 
76
81
  // 1. Check for dangling references (invalid routes)
@@ -103,14 +108,21 @@ function validateGraph(graph) {
103
108
  }
104
109
  }
105
110
 
106
- // Find orphaned nodes
111
+ // Classify orphaned nodes: deprecated/standalone → warning, others → warning too
112
+ // (orphaned nodes are informational, not fatal — dangling refs are fatal)
107
113
  for (const nodeId of nodeIds) {
108
114
  if (!reachable.has(nodeId)) {
109
- errors.push(`Orphaned node "${nodeId}" is unreachable from entry point`);
115
+ const node = graph.nodes.get(nodeId);
116
+ const status = node?.runtime_status || '';
117
+ if (status === 'deprecated') {
118
+ warnings.push(`Deprecated node "${nodeId}" is unreachable from entry point`);
119
+ } else {
120
+ warnings.push(`Orphaned node "${nodeId}" is unreachable from entry point`);
121
+ }
110
122
  }
111
123
  }
112
124
 
113
- return { valid: errors.length === 0, errors };
125
+ return { valid: errors.length === 0, errors, warnings };
114
126
  }
115
127
 
116
128
  /**
@@ -50,9 +50,19 @@ class FlowEngine {
50
50
  );
51
51
  }
52
52
 
53
+ this._validationWarnings = validation.warnings || [];
53
54
  return this;
54
55
  }
55
56
 
57
+ /**
58
+ * Get validation warnings from the last loadFlow() call.
59
+ * Warnings are informational (e.g. orphaned nodes) and do not prevent flow execution.
60
+ * @returns {string[]}
61
+ */
62
+ getValidationWarnings() {
63
+ return this._validationWarnings || [];
64
+ }
65
+
56
66
  /**
57
67
  * Get a node by ID.
58
68
  * @param {string} id
@@ -73,17 +73,18 @@ registerFunction('collectErrors', (context) => {
73
73
  registerFunction('hasCriticalIssues', (context, obj) => {
74
74
  if (!obj) return false;
75
75
  const json = typeof obj === 'string' ? obj : JSON.stringify(obj);
76
+ const jsonLower = json.toLowerCase();
76
77
 
77
- // Enhanced pattern detection for critical issues
78
+ // Case-insensitive pattern detection for critical issues
78
79
  const criticalPatterns = [
79
80
  '"critical"',
80
81
  '"blocking"',
81
- '"P0"',
82
- '"MUST_FIX"',
83
- '"URGENT"'
82
+ '"p0"',
83
+ '"must_fix"',
84
+ '"urgent"'
84
85
  ];
85
86
 
86
- return criticalPatterns.some(pattern => json.includes(pattern));
87
+ return criticalPatterns.some(pattern => jsonLower.includes(pattern));
87
88
  });
88
89
 
89
90
  registerFunction('generateSummary', (context) => {
@@ -48,10 +48,11 @@ describe('CLI: helpers', () => {
48
48
  // ---------- validate ----------
49
49
 
50
50
  describe('CLI: validate', () => {
51
- it('reports valid flow with 44 nodes', async () => {
51
+ it('reports valid flow with correct node count', async () => {
52
52
  const result = await main(['node', 'cli.js', 'validate', '--flow', FLOW_PATH]);
53
+ const flow = require('../../flows/development-flow.json');
53
54
  assert.equal(result.valid, true);
54
- assert.equal(result.nodeCount, 44);
55
+ assert.equal(result.nodeCount, flow.nodes.length);
55
56
  assert.ok(result.parallelNodes.length >= 4);
56
57
  });
57
58
 
@@ -385,7 +385,8 @@ describe('Execute Dispatcher: Error Handling', () => {
385
385
 
386
386
  it('condition node throws when branch is missing', async () => {
387
387
  const executor = getExecutor('condition');
388
- const ctx = makeContext({ inputs: { val: true } });
388
+ // Condition evaluates to false, but no "false" branch is defined
389
+ const ctx = makeContext({ inputs: { val: false } });
389
390
  await assert.rejects(
390
391
  executor(
391
392
  { id: 'cond', type: 'condition', condition: '{{inputs.val}}', true: 'next' },
@@ -160,8 +160,8 @@ describe('flow validation enhancements', () => {
160
160
  ]
161
161
  });
162
162
  const result = validateGraph(graph);
163
- assert.equal(result.valid, false);
164
- assert.ok(result.errors.some(e => e.includes('orphan') && e.includes('unreachable')));
163
+ assert.equal(result.valid, true); // orphans are warnings, not errors
164
+ assert.ok(result.warnings.some(e => e.includes('orphan') && e.includes('unreachable')));
165
165
  });
166
166
 
167
167
  it('detects orphaned nodes in complex branching', () => {
@@ -175,9 +175,9 @@ describe('flow validation enhancements', () => {
175
175
  ]
176
176
  });
177
177
  const result = validateGraph(graph);
178
- assert.equal(result.valid, false);
179
- assert.ok(result.errors.some(e => e.includes('isolated_branch') && e.includes('unreachable')));
180
- assert.ok(result.errors.some(e => e.includes('isolated_end') && e.includes('unreachable')));
178
+ assert.equal(result.valid, true); // orphans are warnings, not errors
179
+ assert.ok(result.warnings.some(e => e.includes('isolated_branch') && e.includes('unreachable')));
180
+ assert.ok(result.warnings.some(e => e.includes('isolated_end') && e.includes('unreachable')));
181
181
  });
182
182
 
183
183
  it('validates onMaxIterations handler references', () => {
@@ -229,11 +229,11 @@ describe('flow validation enhancements', () => {
229
229
  ]
230
230
  });
231
231
  const result = validateGraph(graph);
232
- assert.equal(result.valid, false);
232
+ assert.equal(result.valid, false); // dangling ref is a real error
233
233
  // Should have dangling reference error (missing_next)
234
234
  assert.ok(result.errors.some(e => e.includes('missing_next')));
235
- // Should have orphaned node errors
236
- assert.ok(result.errors.some(e => e.includes('orphan')));
235
+ // Orphaned nodes are warnings, not errors
236
+ assert.ok(result.warnings.some(e => e.includes('orphan')));
237
237
  });
238
238
 
239
239
  it('passes validation for graph with all error handlers', () => {
@@ -276,9 +276,9 @@ describe('flow validation enhancements', () => {
276
276
  ]
277
277
  });
278
278
  const result = validateGraph(graph);
279
- assert.equal(result.valid, false);
280
- assert.ok(result.errors.some(e => e.includes('circular_a') && e.includes('unreachable')));
281
- assert.ok(result.errors.some(e => e.includes('circular_b') && e.includes('unreachable')));
279
+ assert.equal(result.valid, true); // orphans are warnings, not errors
280
+ assert.ok(result.warnings.some(e => e.includes('circular_a') && e.includes('unreachable')));
281
+ assert.ok(result.warnings.some(e => e.includes('circular_b') && e.includes('unreachable')));
282
282
  });
283
283
 
284
284
  it('validates condition node with both branches pointing to same target', () => {
@@ -316,12 +316,15 @@ describe('flow validation enhancements', () => {
316
316
  ]
317
317
  });
318
318
  const result = validateGraph(graph);
319
- assert.equal(result.valid, false);
320
- // Check error message format includes node IDs and issue type
319
+ assert.equal(result.valid, false); // dangling refs are real errors
320
+ // Check error message format for dangling references
321
+ assert.ok(result.errors.length > 0);
321
322
  result.errors.forEach(err => {
322
323
  assert.ok(typeof err === 'string');
323
324
  assert.ok(err.length > 0);
324
325
  });
326
+ // Orphaned node reported as warning
327
+ assert.ok(result.warnings.some(w => w.includes('orphan')));
325
328
  });
326
329
  });
327
330
 
@@ -329,7 +332,7 @@ describe('real flow loading', () => {
329
332
  it('loads the full development-flow.json', () => {
330
333
  const flow = require('../../flows/development-flow.json');
331
334
  const graph = buildGraph(flow);
332
- assert.equal(graph.nodes.size, 44);
335
+ assert.equal(graph.nodes.size, flow.nodes.length);
333
336
  assert.equal(graph.entryNode, 'start');
334
337
  assert.equal(graph.meta.version, '5.3.0');
335
338
  });
@@ -338,17 +341,15 @@ describe('real flow loading', () => {
338
341
  const flow = require('../../flows/development-flow.json');
339
342
  const graph = buildGraph(flow);
340
343
  const result = validateGraph(graph);
341
- // Development flow has known orphaned nodes (P0.3 - teams mode deprecated nodes)
342
- // Expected orphaned nodes: teams_spawn, interrupt_teams_failed, design_ui, interrupt_design_complete
343
- if (!result.valid) {
344
- const orphanedNodes = result.errors.filter(e => e.includes('unreachable'));
345
- assert.ok(orphanedNodes.length > 0, 'Should detect orphaned nodes');
346
- // Verify these are the known teams mode orphaned nodes
347
- const hasTeamsNodes = orphanedNodes.some(e =>
348
- e.includes('teams_spawn') || e.includes('interrupt_teams') ||
349
- e.includes('design_ui') || e.includes('interrupt_design')
350
- );
351
- assert.ok(hasTeamsNodes, 'Orphaned nodes should include known teams mode nodes');
352
- }
344
+ // Flow should be valid (no dangling references)
345
+ assert.equal(result.valid, true, 'Flow should have no dangling reference errors');
346
+ assert.equal(result.errors.length, 0);
347
+ // Known orphaned nodes reported as warnings (deprecated + standalone subflows)
348
+ assert.ok(result.warnings.length > 0, 'Should have warnings for orphaned nodes');
349
+ const hasKnownOrphans = result.warnings.some(w =>
350
+ w.includes('teams_spawn') || w.includes('interrupt_teams') ||
351
+ w.includes('design_ui') || w.includes('interrupt_design')
352
+ );
353
+ assert.ok(hasKnownOrphans, 'Warnings should include known orphaned nodes');
353
354
  });
354
355
  });