elsabro 2.1.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agents/elsabro-orchestrator.md +113 -0
- package/commands/elsabro/add-phase.md +17 -0
- package/commands/elsabro/add-todo.md +111 -53
- package/commands/elsabro/audit-milestone.md +19 -0
- package/commands/elsabro/check-todos.md +210 -31
- package/commands/elsabro/complete-milestone.md +20 -1
- package/commands/elsabro/debug.md +19 -0
- package/commands/elsabro/discuss-phase.md +18 -1
- package/commands/elsabro/execute.md +511 -58
- package/commands/elsabro/insert-phase.md +18 -1
- package/commands/elsabro/list-phase-assumptions.md +17 -0
- package/commands/elsabro/new-milestone.md +19 -0
- package/commands/elsabro/new.md +19 -0
- package/commands/elsabro/pause-work.md +19 -0
- package/commands/elsabro/plan-milestone-gaps.md +20 -1
- package/commands/elsabro/plan.md +264 -36
- package/commands/elsabro/progress.md +203 -79
- package/commands/elsabro/quick.md +19 -0
- package/commands/elsabro/remove-phase.md +17 -0
- package/commands/elsabro/research-phase.md +18 -1
- package/commands/elsabro/resume-work.md +19 -0
- package/commands/elsabro/start.md +399 -98
- package/commands/elsabro/verify-work.md +138 -5
- package/hooks/confirm-destructive.sh +145 -0
- package/hooks/hooks-config.json +81 -0
- package/hooks/lint-check.sh +238 -0
- package/hooks/post-edit-test.sh +189 -0
- package/package.json +3 -2
- package/references/SYSTEM_INDEX.md +241 -0
- package/references/command-flow.md +352 -0
- package/references/enforcement-rules.md +331 -0
- package/references/error-contracts-tests.md +1171 -0
- package/references/error-contracts.md +3102 -0
- package/references/error-handling-instructions.md +26 -12
- package/references/parallel-worktrees.md +293 -0
- package/references/state-sync.md +381 -0
- package/references/task-dispatcher.md +388 -0
- package/references/tasks-integration.md +380 -0
- package/scripts/setup-parallel-worktrees.sh +319 -0
- package/skills/api-microservice.md +765 -0
- package/skills/api-setup.md +76 -3
- package/skills/auth-setup.md +46 -6
- package/skills/chrome-extension.md +584 -0
- package/skills/cicd-setup.md +1206 -0
- package/skills/cli-tool.md +884 -0
- package/skills/database-setup.md +41 -5
- package/skills/desktop-app.md +1351 -0
- package/skills/expo-app.md +35 -2
- package/skills/full-stack-app.md +543 -0
- package/skills/memory-update.md +207 -0
- package/skills/mobile-app.md +813 -0
- package/skills/nextjs-app.md +33 -2
- package/skills/payments-setup.md +76 -1
- package/skills/review.md +331 -0
- package/skills/saas-starter.md +639 -0
- package/skills/sentry-setup.md +41 -7
- package/skills/techdebt.md +289 -0
- package/skills/testing-setup.md +1218 -0
- package/skills/tutor.md +219 -0
- package/templates/.planning/notes/.gitkeep +0 -0
- package/templates/CLAUDE.md.template +48 -0
- package/templates/error-handling-config.json +79 -2
- package/templates/mistakes.md.template +52 -0
- package/templates/patterns.md.template +114 -0
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
# ELSABRO Tasks Integration
|
|
2
|
+
|
|
3
|
+
## Propósito
|
|
4
|
+
|
|
5
|
+
Integración del sistema ELSABRO con Claude Code Tasks API. Este documento define cómo ELSABRO usa Tasks API como backend único para tracking de trabajo, reemplazando sistemas duplicados.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Arquitectura Unificada
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
13
|
+
│ ELSABRO + TASKS API INTEGRATION │
|
|
14
|
+
├─────────────────────────────────────────────────────────────────────────────┤
|
|
15
|
+
│ │
|
|
16
|
+
│ ┌─────────────────────┐ ┌──────────────────────────────────────────┐ │
|
|
17
|
+
│ │ ELSABRO COMMANDS │ │ CLAUDE CODE TASKS API │ │
|
|
18
|
+
│ │ (User Interface) │────▶│ (Backend Storage) │ │
|
|
19
|
+
│ └─────────────────────┘ └──────────────────────────────────────────┘ │
|
|
20
|
+
│ │ │ │
|
|
21
|
+
│ │ │ │
|
|
22
|
+
│ ┌────────┴─────────┐ ┌──────────┴─────────────────────────────┐ │
|
|
23
|
+
│ │ High-Level UX │ │ Native Capabilities │ │
|
|
24
|
+
│ │ - /add-todo │ │ - TaskCreate(subject, description) │ │
|
|
25
|
+
│ │ - /check-todos │ │ - TaskUpdate(status, metadata) │ │
|
|
26
|
+
│ │ - /progress │ │ - TaskList() with filters │ │
|
|
27
|
+
│ │ - /pause-work │ │ - TaskGet(id) for details │ │
|
|
28
|
+
│ │ - /resume-work │ │ - blocks/blockedBy dependencies │ │
|
|
29
|
+
│ └──────────────────┘ │ - owner assignment │ │
|
|
30
|
+
│ │ - metadata (flexible key-value) │ │
|
|
31
|
+
│ └──────────────────────────────────────────┘ │
|
|
32
|
+
│ │
|
|
33
|
+
│ ┌────────────────────────────────────────────────────────────────────────┐ │
|
|
34
|
+
│ │ METADATA SCHEMA │ │
|
|
35
|
+
│ │ │ │
|
|
36
|
+
│ │ { │ │
|
|
37
|
+
│ │ "type": "todo|phase|milestone|work", │ │
|
|
38
|
+
│ │ "priority": "critical|high|medium|low", │ │
|
|
39
|
+
│ │ "category": "bug|tech-debt|docs|chore|idea|feature", │ │
|
|
40
|
+
│ │ "due_date": "ISO-8601 | null", │ │
|
|
41
|
+
│ │ "milestone_id": "M001 | null", │ │
|
|
42
|
+
│ │ "phase_id": "P001 | null", │ │
|
|
43
|
+
│ │ "created_by": "user|system", │ │
|
|
44
|
+
│ │ "source_command": "add-todo|plan|execute|etc" │ │
|
|
45
|
+
│ │ } │ │
|
|
46
|
+
│ └────────────────────────────────────────────────────────────────────────┘ │
|
|
47
|
+
│ │
|
|
48
|
+
└─────────────────────────────────────────────────────────────────────────────┘
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Migración de TODOs a Tasks
|
|
54
|
+
|
|
55
|
+
### Antes (Sistema Duplicado)
|
|
56
|
+
|
|
57
|
+
```markdown
|
|
58
|
+
# .planning/TODOS.md
|
|
59
|
+
|
|
60
|
+
## Critical
|
|
61
|
+
- [ ] Fix auth token refresh (#123)
|
|
62
|
+
|
|
63
|
+
## High Priority
|
|
64
|
+
- [ ] Update React to v18.3 (tech-debt)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Después (Tasks API)
|
|
68
|
+
|
|
69
|
+
```javascript
|
|
70
|
+
// Crear TODO como Task
|
|
71
|
+
TaskCreate({
|
|
72
|
+
subject: "Fix auth token refresh",
|
|
73
|
+
description: "Authentication tokens not refreshing correctly. Issue #123",
|
|
74
|
+
activeForm: "Fixing auth token refresh",
|
|
75
|
+
metadata: {
|
|
76
|
+
type: "todo",
|
|
77
|
+
priority: "critical",
|
|
78
|
+
category: "bug",
|
|
79
|
+
issue_ref: "#123",
|
|
80
|
+
source_command: "add-todo"
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// Crear TODO tech-debt
|
|
85
|
+
TaskCreate({
|
|
86
|
+
subject: "Update React to v18.3",
|
|
87
|
+
description: "Upgrade React version for performance improvements",
|
|
88
|
+
activeForm: "Updating React",
|
|
89
|
+
metadata: {
|
|
90
|
+
type: "todo",
|
|
91
|
+
priority: "high",
|
|
92
|
+
category: "tech-debt",
|
|
93
|
+
source_command: "add-todo"
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Comando: /elsabro:add-todo (Actualizado)
|
|
101
|
+
|
|
102
|
+
### Implementación con Tasks API
|
|
103
|
+
|
|
104
|
+
```javascript
|
|
105
|
+
// Usuario ejecuta: /elsabro:add-todo "Fix typo in README" --priority=high --category=docs
|
|
106
|
+
|
|
107
|
+
// 1. Crear Task
|
|
108
|
+
TaskCreate({
|
|
109
|
+
subject: "Fix typo in README",
|
|
110
|
+
description: "User-created TODO item",
|
|
111
|
+
activeForm: "Fixing typo in README",
|
|
112
|
+
metadata: {
|
|
113
|
+
type: "todo",
|
|
114
|
+
priority: "high", // Del argumento --priority
|
|
115
|
+
category: "docs", // Del argumento --category
|
|
116
|
+
due_date: null, // Del argumento --due
|
|
117
|
+
milestone_id: null, // Del argumento --milestone
|
|
118
|
+
created_by: "user",
|
|
119
|
+
source_command: "add-todo",
|
|
120
|
+
created_at: new Date().toISOString()
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// 2. Output
|
|
125
|
+
console.log(`
|
|
126
|
+
✓ TODO added (Task #${task.id})
|
|
127
|
+
|
|
128
|
+
Subject: Fix typo in README
|
|
129
|
+
Priority: high
|
|
130
|
+
Category: docs
|
|
131
|
+
|
|
132
|
+
View all: /elsabro:check-todos
|
|
133
|
+
`);
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Comando: /elsabro:check-todos (Actualizado)
|
|
139
|
+
|
|
140
|
+
### Implementación con Tasks API
|
|
141
|
+
|
|
142
|
+
```javascript
|
|
143
|
+
// Usuario ejecuta: /elsabro:check-todos --priority=high
|
|
144
|
+
|
|
145
|
+
// 1. Obtener todas las Tasks tipo "todo"
|
|
146
|
+
const tasks = TaskList();
|
|
147
|
+
|
|
148
|
+
// 2. Filtrar por metadata.type === "todo"
|
|
149
|
+
const todos = tasks.filter(t => t.metadata?.type === "todo");
|
|
150
|
+
|
|
151
|
+
// 3. Filtrar por prioridad si se especificó
|
|
152
|
+
const filtered = todos.filter(t =>
|
|
153
|
+
!priority || t.metadata?.priority === priority
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
// 4. Agrupar por prioridad
|
|
157
|
+
const grouped = {
|
|
158
|
+
critical: filtered.filter(t => t.metadata?.priority === "critical"),
|
|
159
|
+
high: filtered.filter(t => t.metadata?.priority === "high"),
|
|
160
|
+
medium: filtered.filter(t => t.metadata?.priority === "medium"),
|
|
161
|
+
low: filtered.filter(t => t.metadata?.priority === "low")
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
// 5. Mostrar vista formateada
|
|
165
|
+
console.log(`
|
|
166
|
+
╔══════════════════════════════════════════════════╗
|
|
167
|
+
║ PROJECT TODOs ║
|
|
168
|
+
╠══════════════════════════════════════════════════╣
|
|
169
|
+
|
|
170
|
+
🔴 CRITICAL (${grouped.critical.length})
|
|
171
|
+
${grouped.critical.map(t => `#${t.id} ${t.subject} [${t.metadata.category}]`).join('\n')}
|
|
172
|
+
|
|
173
|
+
🟠 HIGH (${grouped.high.length})
|
|
174
|
+
${grouped.high.map(t => `#${t.id} ${t.subject} [${t.metadata.category}]`).join('\n')}
|
|
175
|
+
|
|
176
|
+
🟡 MEDIUM (${grouped.medium.length})
|
|
177
|
+
${grouped.medium.map(t => `#${t.id} ${t.subject} [${t.metadata.category}]`).join('\n')}
|
|
178
|
+
|
|
179
|
+
⬜ LOW (${grouped.low.length})
|
|
180
|
+
${grouped.low.map(t => `#${t.id} ${t.subject} [${t.metadata.category}]`).join('\n')}
|
|
181
|
+
|
|
182
|
+
╠══════════════════════════════════════════════════╣
|
|
183
|
+
║ Total: ${filtered.length} | Completed: ${completed.length}
|
|
184
|
+
╚══════════════════════════════════════════════════╝
|
|
185
|
+
`);
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Acciones con TaskUpdate
|
|
189
|
+
|
|
190
|
+
```javascript
|
|
191
|
+
// Marcar como completado
|
|
192
|
+
// /elsabro:check-todos --complete=5
|
|
193
|
+
TaskUpdate({ taskId: "5", status: "completed" });
|
|
194
|
+
|
|
195
|
+
// Cambiar prioridad
|
|
196
|
+
// /elsabro:check-todos --prioritize=6 --to=high
|
|
197
|
+
TaskUpdate({
|
|
198
|
+
taskId: "6",
|
|
199
|
+
metadata: { priority: "high" }
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
// Eliminar (usando status especial)
|
|
203
|
+
// /elsabro:check-todos --delete=9
|
|
204
|
+
TaskUpdate({ taskId: "9", status: "deleted" });
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## State Sync Simplificado
|
|
210
|
+
|
|
211
|
+
### Antes (state-sync.md complejo)
|
|
212
|
+
|
|
213
|
+
```javascript
|
|
214
|
+
// 20+ líneas de código para sincronizar estado
|
|
215
|
+
function initializeState() {
|
|
216
|
+
const stateFile = '.elsabro/state.json';
|
|
217
|
+
let state = { version: "1.0.0", ... };
|
|
218
|
+
// ... mucho código
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Después (Tasks API como fuente de verdad)
|
|
223
|
+
|
|
224
|
+
```javascript
|
|
225
|
+
// Sincronización automática via Tasks API
|
|
226
|
+
function getCommandContext() {
|
|
227
|
+
const tasks = TaskList();
|
|
228
|
+
|
|
229
|
+
return {
|
|
230
|
+
currentCommand: tasks.find(t =>
|
|
231
|
+
t.status === "in_progress" &&
|
|
232
|
+
t.metadata?.type === "command"
|
|
233
|
+
),
|
|
234
|
+
pendingWork: tasks.filter(t => t.status === "pending"),
|
|
235
|
+
blockedWork: tasks.filter(t => t.blockedBy?.length > 0),
|
|
236
|
+
lastCompleted: tasks
|
|
237
|
+
.filter(t => t.status === "completed")
|
|
238
|
+
.sort((a, b) => b.metadata?.completed_at - a.metadata?.completed_at)[0]
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## Tipos de Tasks por Comando
|
|
246
|
+
|
|
247
|
+
### Comando: /elsabro:execute
|
|
248
|
+
|
|
249
|
+
```javascript
|
|
250
|
+
// Fase exploración
|
|
251
|
+
TaskCreate({
|
|
252
|
+
subject: "Explore codebase for feature X",
|
|
253
|
+
metadata: { type: "work", phase: "exploration", model: "haiku" }
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
// Fase implementación
|
|
257
|
+
TaskCreate({
|
|
258
|
+
subject: "Implement feature X",
|
|
259
|
+
metadata: { type: "work", phase: "implementation", model: "opus" }
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
// Fase verificación
|
|
263
|
+
TaskCreate({
|
|
264
|
+
subject: "Verify feature X",
|
|
265
|
+
metadata: { type: "work", phase: "verification", model: "opus" }
|
|
266
|
+
});
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### Comando: /elsabro:plan
|
|
270
|
+
|
|
271
|
+
```javascript
|
|
272
|
+
TaskCreate({
|
|
273
|
+
subject: "Create plan for feature Y",
|
|
274
|
+
metadata: {
|
|
275
|
+
type: "work",
|
|
276
|
+
phase: "planning",
|
|
277
|
+
output_file: ".elsabro/plans/feature-y.md"
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Comando: /elsabro:new-milestone
|
|
283
|
+
|
|
284
|
+
```javascript
|
|
285
|
+
TaskCreate({
|
|
286
|
+
subject: "Milestone: MVP Launch",
|
|
287
|
+
description: "Complete all MVP features for launch",
|
|
288
|
+
metadata: {
|
|
289
|
+
type: "milestone",
|
|
290
|
+
milestone_id: "M001",
|
|
291
|
+
target_date: "2024-02-15",
|
|
292
|
+
phases: ["P001", "P002", "P003"]
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## Dependencias Automáticas
|
|
300
|
+
|
|
301
|
+
```javascript
|
|
302
|
+
// Crear tareas con dependencias
|
|
303
|
+
const phase1 = TaskCreate({
|
|
304
|
+
subject: "Phase 1: Database setup",
|
|
305
|
+
metadata: { type: "phase", phase_id: "P001" }
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
const phase2 = TaskCreate({
|
|
309
|
+
subject: "Phase 2: API endpoints",
|
|
310
|
+
metadata: { type: "phase", phase_id: "P002" }
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
// Phase 2 depende de Phase 1
|
|
314
|
+
TaskUpdate({
|
|
315
|
+
taskId: phase2.id,
|
|
316
|
+
addBlockedBy: [phase1.id]
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
// Resultado: Phase 2 no puede empezar hasta que Phase 1 complete
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## Migración Gradual
|
|
325
|
+
|
|
326
|
+
### Paso 1: Dual-Write (Compatibilidad)
|
|
327
|
+
|
|
328
|
+
```javascript
|
|
329
|
+
// Escribir a ambos sistemas durante transición
|
|
330
|
+
function addTodo(todo) {
|
|
331
|
+
// Nuevo: Tasks API
|
|
332
|
+
TaskCreate({ subject: todo.description, metadata: {...} });
|
|
333
|
+
|
|
334
|
+
// Legacy: .planning/TODOS.md (temporal)
|
|
335
|
+
appendToFile('.planning/TODOS.md', `- [ ] ${todo.description}`);
|
|
336
|
+
}
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Paso 2: Read from Tasks API
|
|
340
|
+
|
|
341
|
+
```javascript
|
|
342
|
+
// Leer solo de Tasks API
|
|
343
|
+
function getTodos() {
|
|
344
|
+
return TaskList().filter(t => t.metadata?.type === "todo");
|
|
345
|
+
}
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### Paso 3: Remove Legacy
|
|
349
|
+
|
|
350
|
+
```javascript
|
|
351
|
+
// Eliminar archivo legacy
|
|
352
|
+
// rm .planning/TODOS.md
|
|
353
|
+
// Actualizar comandos para usar solo Tasks API
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
---
|
|
357
|
+
|
|
358
|
+
## Beneficios de la Integración
|
|
359
|
+
|
|
360
|
+
| Aspecto | Antes | Después |
|
|
361
|
+
|---------|-------|---------|
|
|
362
|
+
| Storage | `.planning/TODOS.md` + `.elsabro/state.json` | Tasks API (único) |
|
|
363
|
+
| Dependencias | Manual | `blocks/blockedBy` nativo |
|
|
364
|
+
| Persistencia | Por sesión | Entre sesiones |
|
|
365
|
+
| Filtros | Código custom | TaskList nativo |
|
|
366
|
+
| Estado | Sincronización manual | Automático |
|
|
367
|
+
| Visualización | Parsing de markdown | Structured data |
|
|
368
|
+
|
|
369
|
+
---
|
|
370
|
+
|
|
371
|
+
## Checklist de Implementación
|
|
372
|
+
|
|
373
|
+
- [ ] Actualizar `/elsabro:add-todo` para usar TaskCreate
|
|
374
|
+
- [ ] Actualizar `/elsabro:check-todos` para usar TaskList/TaskUpdate
|
|
375
|
+
- [ ] Actualizar `/elsabro:progress` para leer de Tasks API
|
|
376
|
+
- [ ] Actualizar `/elsabro:pause-work` para usar TaskUpdate
|
|
377
|
+
- [ ] Actualizar `/elsabro:resume-work` para usar TaskGet
|
|
378
|
+
- [ ] Deprecar `.planning/TODOS.md`
|
|
379
|
+
- [ ] Migrar state-sync a usar Tasks API metadata
|
|
380
|
+
- [ ] Actualizar enforcement-rules.md con nuevos patrones
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ELSABRO Parallel Worktrees Setup
|
|
3
|
+
# Crea worktrees automaticos para ejecucion paralela de agentes
|
|
4
|
+
#
|
|
5
|
+
# Basado en: claude-productivity-plugin/scripts/setup-worktrees.sh
|
|
6
|
+
# Adaptado para el sistema de agentes de ELSABRO
|
|
7
|
+
|
|
8
|
+
set -e
|
|
9
|
+
|
|
10
|
+
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
|
|
11
|
+
WORKTREE_BASE="${REPO_ROOT}/../elsabro-worktrees"
|
|
12
|
+
|
|
13
|
+
# Colores
|
|
14
|
+
RED='\033[0;31m'
|
|
15
|
+
GREEN='\033[0;32m'
|
|
16
|
+
YELLOW='\033[1;33m'
|
|
17
|
+
BLUE='\033[0;34m'
|
|
18
|
+
NC='\033[0m'
|
|
19
|
+
|
|
20
|
+
# Agentes disponibles en ELSABRO
|
|
21
|
+
ELSABRO_AGENTS=("analyst" "executor" "verifier" "planner" "orchestrator")
|
|
22
|
+
|
|
23
|
+
# Limite maximo de worktrees simultaneos
|
|
24
|
+
MAX_WORKTREES=5
|
|
25
|
+
|
|
26
|
+
print_header() {
|
|
27
|
+
echo ""
|
|
28
|
+
echo -e "${BLUE}========================================${NC}"
|
|
29
|
+
echo -e "${BLUE} ELSABRO Parallel Worktrees Setup ${NC}"
|
|
30
|
+
echo -e "${BLUE}========================================${NC}"
|
|
31
|
+
echo ""
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
check_git_repo() {
|
|
35
|
+
if ! git rev-parse --git-dir > /dev/null 2>&1; then
|
|
36
|
+
echo -e "${RED}Error: No estas en un repositorio git${NC}"
|
|
37
|
+
exit 1
|
|
38
|
+
fi
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
check_git_version() {
|
|
42
|
+
local git_version=$(git --version | grep -oE '[0-9]+\.[0-9]+' | head -1)
|
|
43
|
+
local major=$(echo "$git_version" | cut -d. -f1)
|
|
44
|
+
local minor=$(echo "$git_version" | cut -d. -f2)
|
|
45
|
+
|
|
46
|
+
if [ "$major" -lt 2 ] || ([ "$major" -eq 2 ] && [ "$minor" -lt 15 ]); then
|
|
47
|
+
echo -e "${RED}Error: Se requiere git >= 2.15 (tienes $git_version)${NC}"
|
|
48
|
+
exit 1
|
|
49
|
+
fi
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
# Crear directorio base si no existe
|
|
53
|
+
ensure_worktree_base() {
|
|
54
|
+
if [ ! -d "$WORKTREE_BASE" ]; then
|
|
55
|
+
mkdir -p "$WORKTREE_BASE"
|
|
56
|
+
echo -e "${GREEN}Directorio base creado: ${WORKTREE_BASE}${NC}"
|
|
57
|
+
fi
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
# Contar worktrees activos
|
|
61
|
+
count_active_worktrees() {
|
|
62
|
+
local count=$(git worktree list | grep -c "elsabro-worktrees" || echo "0")
|
|
63
|
+
echo "$count"
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
# Funcion para crear worktree para un agente
|
|
67
|
+
create_agent_worktree() {
|
|
68
|
+
local agent_name="$1"
|
|
69
|
+
local worktree_path="${WORKTREE_BASE}/${agent_name}-wt"
|
|
70
|
+
local branch_name="elsabro/${agent_name}"
|
|
71
|
+
|
|
72
|
+
# Verificar limite de worktrees
|
|
73
|
+
local active=$(count_active_worktrees)
|
|
74
|
+
if [ "$active" -ge "$MAX_WORKTREES" ]; then
|
|
75
|
+
echo -e "${RED}Error: Limite de worktrees alcanzado (${MAX_WORKTREES})${NC}"
|
|
76
|
+
echo -e "${YELLOW}Usa 'cleanup' para liberar worktrees${NC}"
|
|
77
|
+
return 1
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
# Si ya existe, limpiar
|
|
81
|
+
if [ -d "$worktree_path" ]; then
|
|
82
|
+
echo -e "${YELLOW}Limpiando worktree existente: ${agent_name}${NC}"
|
|
83
|
+
git worktree remove "$worktree_path" --force 2>/dev/null || true
|
|
84
|
+
git branch -D "$branch_name" 2>/dev/null || true
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
# Crear branch desde HEAD actual
|
|
88
|
+
echo -e "${GREEN}Creando worktree: ${agent_name}${NC}"
|
|
89
|
+
git branch "$branch_name" HEAD 2>/dev/null || git branch -D "$branch_name" && git branch "$branch_name" HEAD
|
|
90
|
+
git worktree add "$worktree_path" "$branch_name"
|
|
91
|
+
|
|
92
|
+
echo -e "${GREEN} Path: ${worktree_path}${NC}"
|
|
93
|
+
echo -e "${GREEN} Branch: ${branch_name}${NC}"
|
|
94
|
+
echo "$worktree_path"
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
# Funcion para merge de worktree
|
|
98
|
+
merge_agent_worktree() {
|
|
99
|
+
local agent_name="$1"
|
|
100
|
+
local branch_name="elsabro/${agent_name}"
|
|
101
|
+
local current_branch=$(git rev-parse --abbrev-ref HEAD)
|
|
102
|
+
|
|
103
|
+
# Verificar que la branch existe
|
|
104
|
+
if ! git show-ref --verify --quiet "refs/heads/${branch_name}"; then
|
|
105
|
+
echo -e "${RED}Error: Branch ${branch_name} no existe${NC}"
|
|
106
|
+
return 1
|
|
107
|
+
fi
|
|
108
|
+
|
|
109
|
+
# Verificar si hay cambios para mergear
|
|
110
|
+
local changes=$(git log "${current_branch}..${branch_name}" --oneline 2>/dev/null | wc -l | tr -d ' ')
|
|
111
|
+
if [ "$changes" -eq 0 ]; then
|
|
112
|
+
echo -e "${YELLOW}No hay cambios en ${branch_name} para mergear${NC}"
|
|
113
|
+
return 0
|
|
114
|
+
fi
|
|
115
|
+
|
|
116
|
+
echo -e "${GREEN}Merging ${agent_name} into ${current_branch}${NC}"
|
|
117
|
+
echo -e "${BLUE} Commits a mergear: ${changes}${NC}"
|
|
118
|
+
|
|
119
|
+
# Intentar merge
|
|
120
|
+
if git merge "$branch_name" --no-edit -m "Merge: ELSABRO ${agent_name} parallel work"; then
|
|
121
|
+
echo -e "${GREEN} Merge exitoso${NC}"
|
|
122
|
+
else
|
|
123
|
+
echo -e "${RED} Conflictos detectados. Resuelve manualmente.${NC}"
|
|
124
|
+
echo -e "${YELLOW} Usa 'git merge --abort' para cancelar${NC}"
|
|
125
|
+
return 1
|
|
126
|
+
fi
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
# Funcion para cleanup de un agente especifico
|
|
130
|
+
cleanup_agent_worktree() {
|
|
131
|
+
local agent_name="$1"
|
|
132
|
+
local worktree_path="${WORKTREE_BASE}/${agent_name}-wt"
|
|
133
|
+
local branch_name="elsabro/${agent_name}"
|
|
134
|
+
|
|
135
|
+
if [ -d "$worktree_path" ]; then
|
|
136
|
+
echo -e "${YELLOW}Eliminando worktree: ${agent_name}${NC}"
|
|
137
|
+
git worktree remove "$worktree_path" --force 2>/dev/null || true
|
|
138
|
+
fi
|
|
139
|
+
|
|
140
|
+
if git show-ref --verify --quiet "refs/heads/${branch_name}"; then
|
|
141
|
+
git branch -D "$branch_name" 2>/dev/null || true
|
|
142
|
+
echo -e "${GREEN} Branch ${branch_name} eliminada${NC}"
|
|
143
|
+
fi
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
# Funcion para cleanup de todos los worktrees
|
|
147
|
+
cleanup_worktrees() {
|
|
148
|
+
echo -e "${YELLOW}Limpiando worktrees de ELSABRO...${NC}"
|
|
149
|
+
|
|
150
|
+
# Limpiar por directorio
|
|
151
|
+
if [ -d "$WORKTREE_BASE" ]; then
|
|
152
|
+
for wt in "$WORKTREE_BASE"/*-wt; do
|
|
153
|
+
if [ -d "$wt" ]; then
|
|
154
|
+
local name=$(basename "$wt" | sed 's/-wt$//')
|
|
155
|
+
echo -e "${YELLOW} Eliminando: ${name}${NC}"
|
|
156
|
+
git worktree remove "$wt" --force 2>/dev/null || true
|
|
157
|
+
git branch -D "elsabro/${name}" 2>/dev/null || true
|
|
158
|
+
fi
|
|
159
|
+
done
|
|
160
|
+
|
|
161
|
+
# Eliminar directorio base si esta vacio
|
|
162
|
+
rmdir "$WORKTREE_BASE" 2>/dev/null || true
|
|
163
|
+
fi
|
|
164
|
+
|
|
165
|
+
# Limpiar worktrees huerfanos
|
|
166
|
+
git worktree prune
|
|
167
|
+
|
|
168
|
+
echo -e "${GREEN}Worktrees limpiados${NC}"
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
# Funcion para mostrar status
|
|
172
|
+
show_status() {
|
|
173
|
+
echo -e "${BLUE}Worktrees activos:${NC}"
|
|
174
|
+
git worktree list
|
|
175
|
+
echo ""
|
|
176
|
+
|
|
177
|
+
echo -e "${BLUE}Branches de ELSABRO:${NC}"
|
|
178
|
+
git branch --list "elsabro/*" 2>/dev/null || echo " (ninguna)"
|
|
179
|
+
echo ""
|
|
180
|
+
|
|
181
|
+
local active=$(count_active_worktrees)
|
|
182
|
+
echo -e "${BLUE}Worktrees ELSABRO: ${active}/${MAX_WORKTREES}${NC}"
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
# Crear worktrees para todos los agentes de una wave
|
|
186
|
+
create_wave_worktrees() {
|
|
187
|
+
local agents=("$@")
|
|
188
|
+
|
|
189
|
+
if [ ${#agents[@]} -eq 0 ]; then
|
|
190
|
+
echo -e "${RED}Error: Especifica los agentes para la wave${NC}"
|
|
191
|
+
return 1
|
|
192
|
+
fi
|
|
193
|
+
|
|
194
|
+
echo -e "${BLUE}Creando worktrees para wave: ${agents[*]}${NC}"
|
|
195
|
+
|
|
196
|
+
for agent in "${agents[@]}"; do
|
|
197
|
+
create_agent_worktree "$agent"
|
|
198
|
+
done
|
|
199
|
+
|
|
200
|
+
echo ""
|
|
201
|
+
show_status
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
# Merge y cleanup de una wave completa
|
|
205
|
+
complete_wave() {
|
|
206
|
+
local agents=("$@")
|
|
207
|
+
|
|
208
|
+
if [ ${#agents[@]} -eq 0 ]; then
|
|
209
|
+
echo -e "${RED}Error: Especifica los agentes de la wave${NC}"
|
|
210
|
+
return 1
|
|
211
|
+
fi
|
|
212
|
+
|
|
213
|
+
echo -e "${BLUE}Completando wave: ${agents[*]}${NC}"
|
|
214
|
+
|
|
215
|
+
# Merge todos los agentes
|
|
216
|
+
for agent in "${agents[@]}"; do
|
|
217
|
+
merge_agent_worktree "$agent"
|
|
218
|
+
done
|
|
219
|
+
|
|
220
|
+
# Cleanup
|
|
221
|
+
for agent in "${agents[@]}"; do
|
|
222
|
+
cleanup_agent_worktree "$agent"
|
|
223
|
+
done
|
|
224
|
+
|
|
225
|
+
echo ""
|
|
226
|
+
echo -e "${GREEN}Wave completada${NC}"
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
# Mostrar ayuda
|
|
230
|
+
show_help() {
|
|
231
|
+
echo "ELSABRO Parallel Worktrees"
|
|
232
|
+
echo ""
|
|
233
|
+
echo "Uso: $0 <comando> [argumentos]"
|
|
234
|
+
echo ""
|
|
235
|
+
echo "Comandos:"
|
|
236
|
+
echo " create <agentes...> Crear worktrees para agentes especificos"
|
|
237
|
+
echo " merge <agentes...> Merge branches de agentes al branch actual"
|
|
238
|
+
echo " cleanup [agentes...] Limpiar worktrees (todos si no se especifica)"
|
|
239
|
+
echo " complete <agentes...> Merge y cleanup de una wave"
|
|
240
|
+
echo " status Mostrar estado de worktrees"
|
|
241
|
+
echo " list Listar todos los worktrees (git worktree list)"
|
|
242
|
+
echo ""
|
|
243
|
+
echo "Agentes disponibles: ${ELSABRO_AGENTS[*]}"
|
|
244
|
+
echo ""
|
|
245
|
+
echo "Ejemplos:"
|
|
246
|
+
echo " $0 create analyst executor verifier"
|
|
247
|
+
echo " $0 merge analyst executor"
|
|
248
|
+
echo " $0 complete analyst executor verifier"
|
|
249
|
+
echo " $0 cleanup"
|
|
250
|
+
echo " $0 status"
|
|
251
|
+
echo ""
|
|
252
|
+
echo "Limites:"
|
|
253
|
+
echo " - Maximo ${MAX_WORKTREES} worktrees simultaneos"
|
|
254
|
+
echo " - Requiere git >= 2.15"
|
|
255
|
+
echo " - Worktrees en: ${WORKTREE_BASE}"
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
# Main
|
|
259
|
+
main() {
|
|
260
|
+
check_git_repo
|
|
261
|
+
check_git_version
|
|
262
|
+
ensure_worktree_base
|
|
263
|
+
|
|
264
|
+
case "$1" in
|
|
265
|
+
create)
|
|
266
|
+
shift
|
|
267
|
+
if [ $# -eq 0 ]; then
|
|
268
|
+
echo -e "${RED}Error: Especifica al menos un agente${NC}"
|
|
269
|
+
echo "Agentes disponibles: ${ELSABRO_AGENTS[*]}"
|
|
270
|
+
exit 1
|
|
271
|
+
fi
|
|
272
|
+
for agent in "$@"; do
|
|
273
|
+
create_agent_worktree "$agent"
|
|
274
|
+
done
|
|
275
|
+
;;
|
|
276
|
+
merge)
|
|
277
|
+
shift
|
|
278
|
+
if [ $# -eq 0 ]; then
|
|
279
|
+
echo -e "${RED}Error: Especifica al menos un agente${NC}"
|
|
280
|
+
exit 1
|
|
281
|
+
fi
|
|
282
|
+
for agent in "$@"; do
|
|
283
|
+
merge_agent_worktree "$agent"
|
|
284
|
+
done
|
|
285
|
+
;;
|
|
286
|
+
cleanup)
|
|
287
|
+
shift
|
|
288
|
+
if [ $# -eq 0 ]; then
|
|
289
|
+
cleanup_worktrees
|
|
290
|
+
else
|
|
291
|
+
for agent in "$@"; do
|
|
292
|
+
cleanup_agent_worktree "$agent"
|
|
293
|
+
done
|
|
294
|
+
fi
|
|
295
|
+
;;
|
|
296
|
+
complete)
|
|
297
|
+
shift
|
|
298
|
+
complete_wave "$@"
|
|
299
|
+
;;
|
|
300
|
+
status)
|
|
301
|
+
print_header
|
|
302
|
+
show_status
|
|
303
|
+
;;
|
|
304
|
+
list)
|
|
305
|
+
git worktree list
|
|
306
|
+
;;
|
|
307
|
+
help|--help|-h)
|
|
308
|
+
print_header
|
|
309
|
+
show_help
|
|
310
|
+
;;
|
|
311
|
+
*)
|
|
312
|
+
print_header
|
|
313
|
+
show_help
|
|
314
|
+
exit 1
|
|
315
|
+
;;
|
|
316
|
+
esac
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
main "$@"
|