elsabro 4.0.0 → 4.2.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 +61 -7
- package/agents/elsabro-orchestrator.md +70 -20
- package/agents/elsabro-ux-designer.md +70 -0
- package/commands/elsabro/add-phase.md +20 -0
- package/commands/elsabro/add-todo.md +30 -0
- package/commands/elsabro/audit-milestone.md +20 -0
- package/commands/elsabro/check-todos.md +29 -0
- package/commands/elsabro/complete-milestone.md +20 -0
- package/commands/elsabro/debug.md +76 -1
- package/commands/elsabro/design-ui.md +407 -0
- package/commands/elsabro/discuss-phase.md +20 -0
- package/commands/elsabro/execute.md +166 -30
- package/commands/elsabro/exit.md +97 -0
- package/commands/elsabro/help.md +7 -1
- package/commands/elsabro/insert-phase.md +20 -0
- package/commands/elsabro/list-phase-assumptions.md +20 -0
- package/commands/elsabro/map-codebase.md +30 -0
- package/commands/elsabro/new-milestone.md +23 -0
- package/commands/elsabro/new.md +64 -0
- package/commands/elsabro/pause-work.md +28 -5
- package/commands/elsabro/plan-milestone-gaps.md +20 -0
- package/commands/elsabro/plan.md +20 -0
- package/commands/elsabro/progress.md +8 -0
- package/commands/elsabro/quick.md +58 -3
- package/commands/elsabro/remove-phase.md +20 -0
- package/commands/elsabro/research-phase.md +20 -0
- package/commands/elsabro/resume-work.md +21 -0
- package/commands/elsabro/set-profile.md +38 -0
- package/commands/elsabro/settings.md +38 -0
- package/commands/elsabro/start.md +31 -1
- package/commands/elsabro/update.md +28 -0
- package/commands/elsabro/verify-work.md +94 -7
- package/commands/elsabro/verify.md +30 -0
- package/hooks/elsabro-mode.sh +102 -0
- package/hooks/hooks-config-updated.json +43 -7
- package/hooks/skill-discovery.sh +38 -8
- package/package.json +5 -5
- package/references/SYSTEM_INDEX.md +9 -0
- package/references/agent-teams-integration.md +99 -36
- package/references/enforcement-rules.md +177 -62
- package/references/flow-orchestration.md +127 -32
- package/references/next-step-engine.md +134 -0
- package/skills/stitch-ui-design.md +242 -0
- package/templates/session-state.json +3 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: flow-orchestration
|
|
3
3
|
description: Sistema de orquestacion basado en grafos inspirado en LangGraph
|
|
4
|
-
version:
|
|
4
|
+
version: 4.0.0
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# ELSABRO Flow-Based Orchestration
|
|
@@ -628,14 +628,15 @@ class FlowEngine {
|
|
|
628
628
|
async executeTeamNode(node) {
|
|
629
629
|
const config = this.resolveTemplate(node.config);
|
|
630
630
|
const phaseOutputs = {};
|
|
631
|
+
let teamCreated = false;
|
|
631
632
|
|
|
632
633
|
try {
|
|
633
|
-
// 1. Crear equipo
|
|
634
|
-
await this.callTool('
|
|
635
|
-
operation: 'spawnTeam',
|
|
634
|
+
// 1. Crear equipo (API oficial Claude Code)
|
|
635
|
+
await this.callTool('TeamCreate', {
|
|
636
636
|
team_name: config.team_name,
|
|
637
637
|
description: config.description
|
|
638
638
|
});
|
|
639
|
+
teamCreated = true;
|
|
639
640
|
|
|
640
641
|
// 2. Ejecutar fases secuencialmente
|
|
641
642
|
for (const phase of node.phases) {
|
|
@@ -643,42 +644,66 @@ class FlowEngine {
|
|
|
643
644
|
phase.active_members.includes(m.name)
|
|
644
645
|
);
|
|
645
646
|
|
|
646
|
-
// Spawn miembros activos en paralelo
|
|
647
|
-
const memberPromises = activeMembers.map(member =>
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
647
|
+
// Spawn miembros activos en paralelo (with per-member error context)
|
|
648
|
+
const memberPromises = activeMembers.map(async (member) => {
|
|
649
|
+
try {
|
|
650
|
+
return await this.callTool('Task', {
|
|
651
|
+
subagent_type: member.agent,
|
|
652
|
+
team_name: config.team_name,
|
|
653
|
+
name: member.name,
|
|
654
|
+
model: member.model,
|
|
655
|
+
description: `${phase.name}: ${member.role}`,
|
|
656
|
+
prompt: this.resolveTemplate(phase.tasks)
|
|
657
|
+
});
|
|
658
|
+
} catch (error) {
|
|
659
|
+
this.state.history.push({
|
|
660
|
+
nodeId: node.id,
|
|
661
|
+
event: 'member_spawn_failed',
|
|
662
|
+
phase: phase.id,
|
|
663
|
+
member: member.name,
|
|
664
|
+
agent: member.agent,
|
|
665
|
+
error: error.message,
|
|
666
|
+
timestamp: new Date().toISOString()
|
|
667
|
+
});
|
|
668
|
+
throw new Error(
|
|
669
|
+
`Failed to spawn '${member.name}' (${member.agent}) in phase '${phase.id}': ${error.message}`
|
|
670
|
+
);
|
|
671
|
+
}
|
|
672
|
+
});
|
|
673
|
+
|
|
674
|
+
// Capturar resultados de cada fase (with phase context on failure)
|
|
675
|
+
try {
|
|
676
|
+
const results = await Promise.all(memberPromises);
|
|
677
|
+
phaseOutputs[phase.id] = results;
|
|
678
|
+
} catch (error) {
|
|
679
|
+
throw new Error(`Phase '${phase.id}' failed: ${error.message}`);
|
|
680
|
+
}
|
|
661
681
|
}
|
|
662
682
|
|
|
663
683
|
// 3. Cleanup si configurado
|
|
664
684
|
if (node.cleanup) {
|
|
665
|
-
|
|
666
|
-
for (const member of node.members) {
|
|
667
|
-
await this.callTool('SendMessage', {
|
|
668
|
-
type: 'shutdown_request',
|
|
669
|
-
recipient: member.name,
|
|
670
|
-
content: 'Phase complete, shutting down'
|
|
671
|
-
});
|
|
672
|
-
}
|
|
673
|
-
await this.callTool('Teammate', { operation: 'cleanup' });
|
|
685
|
+
await this.cleanupTeam(node, config);
|
|
674
686
|
}
|
|
675
687
|
|
|
676
|
-
// 4.
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
return { next: node.next };
|
|
688
|
+
// 4. Return phases in result so executeNode stores them in nodeOutputs
|
|
689
|
+
return { next: node.next, phases: phaseOutputs };
|
|
680
690
|
|
|
681
691
|
} catch (error) {
|
|
692
|
+
// Attempt cleanup only if team was successfully created
|
|
693
|
+
try {
|
|
694
|
+
if (node.cleanup && teamCreated) {
|
|
695
|
+
await this.cleanupTeam(node, config);
|
|
696
|
+
}
|
|
697
|
+
} catch (cleanupError) {
|
|
698
|
+
// Log cleanup failure but don't mask the original error
|
|
699
|
+
this.state.history.push({
|
|
700
|
+
nodeId: node.id,
|
|
701
|
+
event: 'cleanup_failed',
|
|
702
|
+
error: cleanupError.message,
|
|
703
|
+
timestamp: new Date().toISOString()
|
|
704
|
+
});
|
|
705
|
+
}
|
|
706
|
+
|
|
682
707
|
// Si hay onError definido, redirigir
|
|
683
708
|
if (node.onError) {
|
|
684
709
|
this.state.lastError = error.message;
|
|
@@ -688,6 +713,71 @@ class FlowEngine {
|
|
|
688
713
|
}
|
|
689
714
|
}
|
|
690
715
|
|
|
716
|
+
/**
|
|
717
|
+
* Cleanup: shutdown all teammates and delete team
|
|
718
|
+
* Waits for each shutdown acknowledgment before proceeding to TeamDelete
|
|
719
|
+
*/
|
|
720
|
+
async cleanupTeam(node, config) {
|
|
721
|
+
const shutdownResults = [];
|
|
722
|
+
|
|
723
|
+
// Send shutdown requests and track each result
|
|
724
|
+
for (const member of node.members) {
|
|
725
|
+
try {
|
|
726
|
+
const result = await this.callTool('SendMessage', {
|
|
727
|
+
type: 'shutdown_request',
|
|
728
|
+
recipient: member.name,
|
|
729
|
+
content: 'Phase complete, shutting down'
|
|
730
|
+
});
|
|
731
|
+
|
|
732
|
+
const wasApproved = !(result && result.approved === false);
|
|
733
|
+
shutdownResults.push({ member: member.name, approved: wasApproved });
|
|
734
|
+
|
|
735
|
+
if (!wasApproved) {
|
|
736
|
+
this.state.history.push({
|
|
737
|
+
nodeId: node.id,
|
|
738
|
+
event: 'shutdown_rejected',
|
|
739
|
+
member: member.name,
|
|
740
|
+
reason: result.content || 'No reason provided',
|
|
741
|
+
timestamp: new Date().toISOString()
|
|
742
|
+
});
|
|
743
|
+
}
|
|
744
|
+
} catch (error) {
|
|
745
|
+
shutdownResults.push({ member: member.name, approved: false, error: error.message });
|
|
746
|
+
this.state.history.push({
|
|
747
|
+
nodeId: node.id,
|
|
748
|
+
event: 'shutdown_request_failed',
|
|
749
|
+
member: member.name,
|
|
750
|
+
error: error.message,
|
|
751
|
+
timestamp: new Date().toISOString()
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
// Check if any shutdowns failed - TeamDelete requires all members inactive
|
|
757
|
+
const failed = shutdownResults.filter(r => !r.approved);
|
|
758
|
+
if (failed.length > 0) {
|
|
759
|
+
const names = failed.map(r => r.member).join(', ');
|
|
760
|
+
throw new Error(
|
|
761
|
+
`Cannot delete team '${config.team_name}': ${failed.length} member(s) did not shut down: ${names}`
|
|
762
|
+
);
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
// All teammates acknowledged shutdown - safe to delete
|
|
766
|
+
try {
|
|
767
|
+
await this.callTool('TeamDelete');
|
|
768
|
+
this.state.history.push({
|
|
769
|
+
nodeId: node.id,
|
|
770
|
+
event: 'team_deleted',
|
|
771
|
+
teamName: config.team_name,
|
|
772
|
+
timestamp: new Date().toISOString()
|
|
773
|
+
});
|
|
774
|
+
} catch (error) {
|
|
775
|
+
throw new Error(
|
|
776
|
+
`Failed to delete team '${config.team_name}' after successful shutdown: ${error.message}`
|
|
777
|
+
);
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
|
|
691
781
|
/**
|
|
692
782
|
* Ejecuta nodo de agente
|
|
693
783
|
*/
|
|
@@ -927,6 +1017,11 @@ class FlowEngine {
|
|
|
927
1017
|
return this.graph.getNode(nextId);
|
|
928
1018
|
}
|
|
929
1019
|
|
|
1020
|
+
// Team node: use result.next for dynamic routing
|
|
1021
|
+
if (currentNode.type === 'team') {
|
|
1022
|
+
return result.next ? this.graph.getNode(result.next) : null;
|
|
1023
|
+
}
|
|
1024
|
+
|
|
930
1025
|
// Exit no tiene siguiente
|
|
931
1026
|
if (currentNode.type === 'exit') {
|
|
932
1027
|
return null;
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# Next Step Engine - Sistema Universal de Sugerencias
|
|
2
|
+
|
|
3
|
+
## Objetivo
|
|
4
|
+
|
|
5
|
+
Cada comando ELSABRO que escribe a `state.json` DEBE sugerir al usuario qué hacer después de completar. Esto crea un flujo guiado que reduce la fricción y ayuda a usuarios sin experiencia.
|
|
6
|
+
|
|
7
|
+
## Implementación
|
|
8
|
+
|
|
9
|
+
### 1. state.json: Campo `suggested_next`
|
|
10
|
+
|
|
11
|
+
Al completar cualquier comando, establecer:
|
|
12
|
+
|
|
13
|
+
```javascript
|
|
14
|
+
state.suggested_next = "[comando]"; // o null si es terminal
|
|
15
|
+
Write(".elsabro/state.json", JSON.stringify(state, null, 2));
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### 2. Output: Bloque "Siguiente Paso"
|
|
19
|
+
|
|
20
|
+
Al final de cada `<process>`, mostrar:
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
## Siguiente Paso
|
|
24
|
+
|
|
25
|
+
→ /elsabro:[primary-suggestion] — [razón contextual]
|
|
26
|
+
→ /elsabro:[alternative] — [razón alternativa]
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Decision Matrix
|
|
30
|
+
|
|
31
|
+
| Comando | suggested_next | Sugerencia Primaria | Alternativa |
|
|
32
|
+
|---------|---------------|---------------------|-------------|
|
|
33
|
+
| start | "map-codebase" | → /elsabro:map-codebase — explorar el proyecto | → /elsabro:plan — planificar directamente |
|
|
34
|
+
| new | "plan" | → /elsabro:plan 1 — planificar primera fase | → /elsabro:map-codebase — explorar lo creado |
|
|
35
|
+
| plan | "execute" | → /elsabro:execute — ejecutar el plan | → /elsabro:discuss-phase — discutir antes |
|
|
36
|
+
| execute | "verify-work" | → /elsabro:verify-work — verificar el trabajo | → /elsabro:progress — ver progreso |
|
|
37
|
+
| verify-work | conditional | → /elsabro:plan [N+1] (si PASS) | → /elsabro:execute (si gaps) |
|
|
38
|
+
| debug | "verify-work" | → /elsabro:verify-work — verificar el fix | → /elsabro:progress — ver estado |
|
|
39
|
+
| quick | "progress" | → /elsabro:progress — ver estado | → commit si hay cambios |
|
|
40
|
+
| map-codebase | "plan" | → /elsabro:plan — planificar basado en hallazgos | → /elsabro:discuss-phase — discutir |
|
|
41
|
+
| resume-work | context-dependent | → /elsabro:[paused_command] — continuar | → /elsabro:progress — ver estado |
|
|
42
|
+
| pause-work | "resume-work" | → /elsabro:resume-work — cuando estés listo | |
|
|
43
|
+
| verify | "progress" | → /elsabro:progress — ver estado general | → /elsabro:plan [N+1] — siguiente fase |
|
|
44
|
+
| new-milestone | "plan" | → /elsabro:plan 1 — planificar primera fase | → /elsabro:add-phase — agregar fases |
|
|
45
|
+
| complete-milestone | "new-milestone" | → /elsabro:new-milestone — siguiente milestone | → /elsabro:progress — ver estado |
|
|
46
|
+
| audit-milestone | "plan-milestone-gaps" | → /elsabro:plan-milestone-gaps — cerrar gaps | → /elsabro:discuss-phase — discutir |
|
|
47
|
+
| plan-milestone-gaps | "execute" | → /elsabro:execute — corregir los gaps | → /elsabro:quick — fix rápido |
|
|
48
|
+
| add-phase | "plan" | → /elsabro:plan [N] — planificar la nueva fase | → /elsabro:progress — ver estado |
|
|
49
|
+
| insert-phase | "plan" | → /elsabro:plan [N] — planificar fase insertada | → /elsabro:progress — ver estado |
|
|
50
|
+
| remove-phase | "progress" | → /elsabro:progress — ver estado actualizado | → /elsabro:plan — replanificar |
|
|
51
|
+
| discuss-phase | "plan" | → /elsabro:plan — planificar la fase discutida | → /elsabro:execute — ejecutar directamente |
|
|
52
|
+
| research-phase | "plan" | → /elsabro:plan — planificar con los hallazgos | → /elsabro:discuss-phase — discutir |
|
|
53
|
+
| list-phase-assumptions | "discuss-phase" | → /elsabro:discuss-phase — discutir asunciones | → /elsabro:plan — planificar |
|
|
54
|
+
| add-todo | "check-todos" | → /elsabro:check-todos — ver lista completa | → /elsabro:quick — resolver ahora |
|
|
55
|
+
| check-todos | "quick" | → /elsabro:quick — resolver un TODO | → /elsabro:execute — trabajo mayor |
|
|
56
|
+
| settings | previous_flow | → volver al flujo anterior | → /elsabro:start — empezar nuevo |
|
|
57
|
+
| set-profile | previous_flow | → volver al flujo anterior | → /elsabro:start — empezar nuevo |
|
|
58
|
+
| update | "start" | → /elsabro:start — usar nueva versión | |
|
|
59
|
+
| design-ui | "execute" | → /elsabro:execute — implementar los diseños | → /elsabro:design-ui — refinar o agregar más |
|
|
60
|
+
| progress | context-dependent | → /elsabro:execute — continuar trabajo activo | → /elsabro:check-todos — revisar pendientes |
|
|
61
|
+
| exit | "resume-work" | → /elsabro:resume-work — cuando vuelvas | |
|
|
62
|
+
|
|
63
|
+
## Contextual Overrides
|
|
64
|
+
|
|
65
|
+
The suggested_next can be overridden based on context:
|
|
66
|
+
|
|
67
|
+
### Si hay pending_tasks bloqueadas
|
|
68
|
+
```javascript
|
|
69
|
+
if (state.pending_tasks?.some(t => t.blocked)) {
|
|
70
|
+
// Override: suggest debugging the blocker
|
|
71
|
+
state.suggested_next = "debug";
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Si hay TODOs de alta prioridad
|
|
76
|
+
```javascript
|
|
77
|
+
if (state.context?.high_priority_todos > 0) {
|
|
78
|
+
// Alternative: suggest checking todos
|
|
79
|
+
alternativeSuggestion = "check-todos";
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Si verify-work encontró gaps
|
|
84
|
+
```javascript
|
|
85
|
+
if (state.context?.verification_result === "FAIL") {
|
|
86
|
+
state.suggested_next = "execute"; // re-execute to fix
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Si es flujo nuevo (greenfield)
|
|
91
|
+
```javascript
|
|
92
|
+
if (state.context?.project_type === "greenfield" && !state.context?.plan_file) {
|
|
93
|
+
state.suggested_next = "new"; // create project first
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Output Template
|
|
98
|
+
|
|
99
|
+
### Formato Estándar
|
|
100
|
+
```
|
|
101
|
+
## Siguiente Paso
|
|
102
|
+
|
|
103
|
+
→ /elsabro:[comando] — [razón]
|
|
104
|
+
→ /elsabro:[alternativa] — [razón]
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Con Contexto Dinámico
|
|
108
|
+
```
|
|
109
|
+
## Siguiente Paso
|
|
110
|
+
|
|
111
|
+
→ /elsabro:execute — ejecutar el plan creado
|
|
112
|
+
[Si prefieres revisar primero: /elsabro:discuss-phase]
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Fallback Rule
|
|
116
|
+
|
|
117
|
+
When uncertain about what to suggest:
|
|
118
|
+
```javascript
|
|
119
|
+
state.suggested_next = "progress"; // safe fallback
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
The `progress` command always shows current state and its own suggestions.
|
|
123
|
+
|
|
124
|
+
## Integration with Persistent Mode
|
|
125
|
+
|
|
126
|
+
When `elsabro_mode` is true, the routing hook can use `suggested_next` to provide smarter routing:
|
|
127
|
+
|
|
128
|
+
```javascript
|
|
129
|
+
// In hook, if user message is ambiguous but suggested_next exists:
|
|
130
|
+
if (state.suggested_next && isAmbiguous(userMessage)) {
|
|
131
|
+
// Route to suggested_next instead of asking for clarification
|
|
132
|
+
Skill(`elsabro:${state.suggested_next}`);
|
|
133
|
+
}
|
|
134
|
+
```
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: stitch-ui-design
|
|
3
|
+
description: Skill para diseño de UI con Stitch AI - genera screens y mockups profesionales desde descripciones de texto
|
|
4
|
+
tags:
|
|
5
|
+
- design
|
|
6
|
+
- ui
|
|
7
|
+
- stitch
|
|
8
|
+
- screens
|
|
9
|
+
- mockups
|
|
10
|
+
- wireframes
|
|
11
|
+
- ux
|
|
12
|
+
difficulty: intermediate
|
|
13
|
+
estimated_time: 15-30 min
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# Skill: Diseño de UI con Stitch AI
|
|
17
|
+
|
|
18
|
+
<when_to_use>
|
|
19
|
+
Usar cuando el usuario menciona:
|
|
20
|
+
- "diseñar interfaz"
|
|
21
|
+
- "crear mockup"
|
|
22
|
+
- "wireframe"
|
|
23
|
+
- "diseño de pantalla"
|
|
24
|
+
- "UI design"
|
|
25
|
+
- "cómo se va a ver"
|
|
26
|
+
- "diseño visual"
|
|
27
|
+
- "generar screens"
|
|
28
|
+
- "prototipo visual"
|
|
29
|
+
</when_to_use>
|
|
30
|
+
|
|
31
|
+
<pre_requisites>
|
|
32
|
+
## Pre-requisitos
|
|
33
|
+
|
|
34
|
+
### Conocimientos
|
|
35
|
+
- Conceptos básicos de UI/UX (no obligatorio - ELSABRO guía)
|
|
36
|
+
- Idea general de qué pantallas necesita la app
|
|
37
|
+
|
|
38
|
+
### Software/Configuración
|
|
39
|
+
- Stitch MCP configurado y funcionando
|
|
40
|
+
- Proyecto ELSABRO inicializado (.elsabro/state.json)
|
|
41
|
+
|
|
42
|
+
### Verificación
|
|
43
|
+
```javascript
|
|
44
|
+
// Verificar que Stitch está disponible
|
|
45
|
+
mcp__stitch__list_projects()
|
|
46
|
+
// Si responde → OK
|
|
47
|
+
// Si error → Verificar configuración MCP
|
|
48
|
+
```
|
|
49
|
+
</pre_requisites>
|
|
50
|
+
|
|
51
|
+
<project_structure>
|
|
52
|
+
## Estructura de Archivos
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
.planning/
|
|
56
|
+
├── ui-designs/
|
|
57
|
+
│ ├── UI-DESIGNS.md # Índice de diseños
|
|
58
|
+
│ ├── screen-login.md # Spec de pantalla login
|
|
59
|
+
│ ├── screen-dashboard.md # Spec de pantalla dashboard
|
|
60
|
+
│ └── screen-settings.md # Spec de pantalla settings
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### UI-DESIGNS.md Template
|
|
64
|
+
```markdown
|
|
65
|
+
# UI Designs - [Nombre del Proyecto]
|
|
66
|
+
|
|
67
|
+
## Stitch Project
|
|
68
|
+
- **ID:** [project_id]
|
|
69
|
+
- **Created:** [fecha]
|
|
70
|
+
- **Screens:** [cantidad]
|
|
71
|
+
|
|
72
|
+
## Screen Index
|
|
73
|
+
| # | Screen | Status | Stitch ID |
|
|
74
|
+
|---|--------|--------|-----------|
|
|
75
|
+
| 1 | Login | ✅ Generated | [id] |
|
|
76
|
+
| 2 | Dashboard | ✅ Generated | [id] |
|
|
77
|
+
| 3 | Settings | 🟡 Draft | [id] |
|
|
78
|
+
```
|
|
79
|
+
</project_structure>
|
|
80
|
+
|
|
81
|
+
<process>
|
|
82
|
+
## Proceso (6 Pasos)
|
|
83
|
+
|
|
84
|
+
### Paso 1: Descubrimiento
|
|
85
|
+
Entender qué screens necesita la app.
|
|
86
|
+
|
|
87
|
+
```javascript
|
|
88
|
+
// Si hay plan de fase, extraer UI requirements
|
|
89
|
+
const plans = Glob(".planning/*-PLAN.md");
|
|
90
|
+
const uiRequirements = plans.flatMap(p => extractUIRequirements(Read(p)));
|
|
91
|
+
|
|
92
|
+
// Si no hay plan, preguntar al usuario
|
|
93
|
+
if (uiRequirements.length === 0) {
|
|
94
|
+
AskUserQuestion({
|
|
95
|
+
questions: [{
|
|
96
|
+
question: "¿Qué pantallas necesita tu app?",
|
|
97
|
+
header: "Screens",
|
|
98
|
+
options: [
|
|
99
|
+
{ label: "Auth flow", description: "Login, Register, Forgot Password" },
|
|
100
|
+
{ label: "Dashboard", description: "Overview con cards y stats" },
|
|
101
|
+
{ label: "CRUD pages", description: "List, Detail, Create, Edit" },
|
|
102
|
+
{ label: "Custom", description: "Describir las pantallas" }
|
|
103
|
+
],
|
|
104
|
+
multiSelect: true
|
|
105
|
+
}]
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Paso 2: Proyecto Stitch
|
|
111
|
+
Crear o reutilizar proyecto en Stitch.
|
|
112
|
+
|
|
113
|
+
```javascript
|
|
114
|
+
const projects = mcp__stitch__list_projects();
|
|
115
|
+
const existing = projects.find(p => p.name.includes(projectName));
|
|
116
|
+
|
|
117
|
+
if (!existing) {
|
|
118
|
+
const project = mcp__stitch__create_project({
|
|
119
|
+
name: projectName + " - UI Design"
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Paso 3: Generación de Screens
|
|
125
|
+
Generar cada screen con Stitch AI.
|
|
126
|
+
|
|
127
|
+
```javascript
|
|
128
|
+
for (const screen of screensToGenerate) {
|
|
129
|
+
const result = mcp__stitch__generate_screen_from_text({
|
|
130
|
+
project_id: projectId,
|
|
131
|
+
text: screen.description
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// Guardar referencia
|
|
135
|
+
screens.push({
|
|
136
|
+
name: screen.name,
|
|
137
|
+
id: result.id,
|
|
138
|
+
description: screen.description
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Paso 4: Revisión
|
|
144
|
+
Revisar screens generados con el usuario.
|
|
145
|
+
|
|
146
|
+
```javascript
|
|
147
|
+
// Listar todos los screens del proyecto
|
|
148
|
+
const allScreens = mcp__stitch__list_screens({ project_id: projectId });
|
|
149
|
+
|
|
150
|
+
// Mostrar resumen al usuario
|
|
151
|
+
// Obtener detalle de cada screen si necesario
|
|
152
|
+
const screenDetail = mcp__stitch__get_screen({
|
|
153
|
+
project_id: projectId,
|
|
154
|
+
screen_id: screenId
|
|
155
|
+
});
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Paso 5: Refinamiento
|
|
159
|
+
Iterar sobre screens según feedback.
|
|
160
|
+
|
|
161
|
+
```javascript
|
|
162
|
+
// Regenerar con ajustes
|
|
163
|
+
mcp__stitch__generate_screen_from_text({
|
|
164
|
+
project_id: projectId,
|
|
165
|
+
text: originalDescription + "\n\nAdjustments:\n" + feedback
|
|
166
|
+
});
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Paso 6: Documentación
|
|
170
|
+
Guardar todo en .planning/ui-designs/.
|
|
171
|
+
|
|
172
|
+
```javascript
|
|
173
|
+
// Crear índice de diseños
|
|
174
|
+
Write(".planning/ui-designs/UI-DESIGNS.md", designIndex);
|
|
175
|
+
|
|
176
|
+
// Crear spec por screen
|
|
177
|
+
for (const screen of screens) {
|
|
178
|
+
Write(`.planning/ui-designs/screen-${screen.slug}.md`, screenSpec);
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
</process>
|
|
182
|
+
|
|
183
|
+
<verification>
|
|
184
|
+
## Verificación
|
|
185
|
+
|
|
186
|
+
### Automática
|
|
187
|
+
```javascript
|
|
188
|
+
// 1. Verificar proyecto existe en Stitch
|
|
189
|
+
const project = mcp__stitch__get_project({ project_id: projectId });
|
|
190
|
+
assert(project, "Proyecto Stitch existe");
|
|
191
|
+
|
|
192
|
+
// 2. Verificar screens generados
|
|
193
|
+
const screens = mcp__stitch__list_screens({ project_id: projectId });
|
|
194
|
+
assert(screens.length > 0, "Al menos 1 screen generado");
|
|
195
|
+
|
|
196
|
+
// 3. Verificar documentación local
|
|
197
|
+
assert(Read(".planning/ui-designs/UI-DESIGNS.md"), "Índice de diseños existe");
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Manual (con usuario)
|
|
201
|
+
```
|
|
202
|
+
Verificación:
|
|
203
|
+
|
|
204
|
+
1. Revisa los screens generados en el proyecto Stitch
|
|
205
|
+
2. ¿Los diseños representan lo que necesitas?
|
|
206
|
+
3. ¿Falta alguna pantalla importante?
|
|
207
|
+
4. ¿Los colores y estilo son apropiados?
|
|
208
|
+
|
|
209
|
+
¿Todo correcto? (sí/ajustar/regenerar)
|
|
210
|
+
```
|
|
211
|
+
</verification>
|
|
212
|
+
|
|
213
|
+
<common_issues>
|
|
214
|
+
## Problemas Comunes
|
|
215
|
+
|
|
216
|
+
### Stitch no responde
|
|
217
|
+
```
|
|
218
|
+
Causa: MCP server no está corriendo o configurado
|
|
219
|
+
Solución: Verificar configuración MCP en settings.json
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Screens genéricos
|
|
223
|
+
```
|
|
224
|
+
Causa: Descripción muy vaga
|
|
225
|
+
Solución: Agregar más detalles: colores, estilo, contenido de ejemplo
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Proyecto duplicado
|
|
229
|
+
```
|
|
230
|
+
Causa: Ya existe un proyecto con el mismo nombre
|
|
231
|
+
Solución: Usar list_projects para encontrar el existente y reutilizarlo
|
|
232
|
+
```
|
|
233
|
+
</common_issues>
|
|
234
|
+
|
|
235
|
+
<next_steps>
|
|
236
|
+
## Siguiente Paso
|
|
237
|
+
|
|
238
|
+
Después de completar el diseño:
|
|
239
|
+
- **Implementar:** `/elsabro:execute` para codificar los diseños
|
|
240
|
+
- **Refinar:** `/elsabro:design-ui` para ajustar screens
|
|
241
|
+
- **Componentes:** Sally (elsabro-ux-designer) puede generar componentes con 21st.dev
|
|
242
|
+
</next_steps>
|