merge: quick/install-commands — agregar commands a repo e instalación
This commit is contained in:
@@ -0,0 +1,154 @@
|
|||||||
|
# Command: create issue
|
||||||
|
|
||||||
|
Crea un issue nuevo en `dev/issues/` siguiendo **estrictamente** la regla `create_issue.md`. Si el issue es grande, lo desglosa automaticamente en sub-issues con feature flags.
|
||||||
|
|
||||||
|
## Inputs
|
||||||
|
|
||||||
|
Se necesitan los datos del issue. Si no se proporcionan, preguntar.
|
||||||
|
|
||||||
|
- `titulo`: titulo corto y descriptivo (ej: "Hot reload de configuracion")
|
||||||
|
- `descripcion`: objetivo/descripcion de lo que se quiere lograr
|
||||||
|
- `dependencias` (opcional): issues de los que depende (ej: "Requiere issue 0010")
|
||||||
|
|
||||||
|
## Flujo obligatorio
|
||||||
|
|
||||||
|
### 1. Determinar el numero del issue
|
||||||
|
|
||||||
|
Buscar el numero mas alto en `dev/issues/` y `dev/issues/completed/` y usar el siguiente.
|
||||||
|
Formato: 4 digitos con ceros a la izquierda (`0023`, `0024`, etc.).
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ls dev/issues/ dev/issues/completed/ | grep -oP '^\d{4}' | sort -rn | head -1
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Generar slug
|
||||||
|
|
||||||
|
A partir del titulo:
|
||||||
|
- Lowercase
|
||||||
|
- Palabras separadas por guiones
|
||||||
|
- Conciso (2-4 palabras)
|
||||||
|
- Ejemplo: "Hot reload de configuracion" → `hot-reload`
|
||||||
|
|
||||||
|
### 3. Evaluar tamano del issue
|
||||||
|
|
||||||
|
Antes de escribir el issue, analizar el alcance y determinar si cabe en **una sola rama corta (horas)**.
|
||||||
|
|
||||||
|
**Criterios para desglosar en sub-issues:**
|
||||||
|
- Toca mas de 2 capas del patron (pkg/ + shell/ + agents/ + tools/)
|
||||||
|
- Requiere mas de ~3 fases de implementacion
|
||||||
|
- El usuario lo indica explicitamente
|
||||||
|
- La descripcion implica multiples componentes independientes
|
||||||
|
|
||||||
|
**Si es un issue simple** (cabe en una rama):
|
||||||
|
- Crear un solo archivo `dev/issues/<NNNN>-<slug>.md`
|
||||||
|
- Seguir directo al paso 4
|
||||||
|
|
||||||
|
**Si es un issue grande** (necesita desglose):
|
||||||
|
- Crear el issue principal `dev/issues/<NNNN>-<slug>.md` con seccion `## Desglose multi-issue`
|
||||||
|
- Crear cada sub-issue como `dev/issues/<NNNN><letra>-<sub-slug>.md` (ej: `0023a-types`, `0023b-client`)
|
||||||
|
- Cada sub-issue es autocontenido: debe compilar, pasar tests, no romper master
|
||||||
|
- Agregar feature flag en la descripcion del issue principal
|
||||||
|
- Registrar todos los sub-issues en `dev/issues/README.md`
|
||||||
|
|
||||||
|
### 4. Crear el issue desde el template
|
||||||
|
|
||||||
|
Copiar `.claude/templates/issue.md` y rellenar **todas** las secciones:
|
||||||
|
|
||||||
|
- **Objetivo**: 1-3 frases claras
|
||||||
|
- **Contexto**: que existe, que falta, dependencias
|
||||||
|
- **Arquitectura**: archivos afectados (marcar `NEW` los nuevos). Explicar que va en `pkg/` (puro) vs `shell/` (impuro)
|
||||||
|
- **Tareas**: fases con tareas numeradas (`1.1`, `1.2`, etc.). Cada tarea concreta y verificable. Siempre incluir fase de tests y fase de cleanup/docs
|
||||||
|
- **Ejemplo de uso**: flujo concreto
|
||||||
|
- **Decisiones de diseno**: justificaciones clave
|
||||||
|
- **Prerequisitos**: que debe existir antes
|
||||||
|
- **Riesgos**: problemas potenciales y mitigacion
|
||||||
|
|
||||||
|
### 5. Para issues multi-issue — contenido adicional
|
||||||
|
|
||||||
|
En el issue principal, agregar despues de las tareas:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## Desglose multi-issue
|
||||||
|
|
||||||
|
Este issue se implementa en sub-issues independientes, cada uno en su propia rama.
|
||||||
|
|
||||||
|
| Sub-issue | Rama | Alcance | Estado |
|
||||||
|
|-----------|------|---------|--------|
|
||||||
|
| <NNNN>a-<slug> | issue/<NNNN>a-<slug> | <que cubre> | pendiente |
|
||||||
|
| <NNNN>b-<slug> | issue/<NNNN>b-<slug> | <que cubre> | pendiente |
|
||||||
|
| ...
|
||||||
|
|
||||||
|
### Feature flag
|
||||||
|
|
||||||
|
Nombre: `<nombre-del-flag>`
|
||||||
|
Se activa en el ultimo sub-issue cuando todo esta integrado.
|
||||||
|
|
||||||
|
### Progreso por tarea
|
||||||
|
|
||||||
|
- [ ] **1.1** <tarea> — sub-issue <NNNN>a
|
||||||
|
- [ ] **1.2** <tarea> — sub-issue <NNNN>a
|
||||||
|
- [ ] **2.1** <tarea> — sub-issue <NNNN>b
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
Cada sub-issue individual debe tener su propio archivo con:
|
||||||
|
- Objetivo especifico del sub-issue
|
||||||
|
- Tareas que le corresponden del issue principal
|
||||||
|
- Nota de que es parte de un issue mayor
|
||||||
|
|
||||||
|
### 6. Registrar feature flag (solo multi-issue)
|
||||||
|
|
||||||
|
Actualizar `dev/feature_flags.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"<nombre-del-flag>": {
|
||||||
|
"enabled": false,
|
||||||
|
"issue": "<NNNN>",
|
||||||
|
"description": "<descripcion breve>",
|
||||||
|
"added": "<YYYY-MM-DD>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7. Actualizar el indice
|
||||||
|
|
||||||
|
En `dev/issues/README.md`, agregar filas al final de la tabla.
|
||||||
|
|
||||||
|
**Issue simple:**
|
||||||
|
```markdown
|
||||||
|
| <N> | <Titulo> | [<NNNN>-<slug>.md](<NNNN>-<slug>.md) | pendiente |
|
||||||
|
```
|
||||||
|
|
||||||
|
**Issue multi-issue (agregar fila por cada sub-issue tambien):**
|
||||||
|
```markdown
|
||||||
|
| <N> | <Titulo> | [<NNNN>-<slug>.md](<NNNN>-<slug>.md) | pendiente |
|
||||||
|
| <N>a | <Titulo> (parte a) | [<NNNN>a-<slug>.md](<NNNN>a-<slug>.md) | pendiente |
|
||||||
|
| <N>b | <Titulo> (parte b) | [<NNNN>b-<slug>.md](<NNNN>b-<slug>.md) | pendiente |
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8. Verificar
|
||||||
|
|
||||||
|
- [ ] Archivo(s) creado(s) en `dev/issues/`
|
||||||
|
- [ ] Todas las secciones del template rellenadas
|
||||||
|
- [ ] Fila(s) agregada(s) en `dev/issues/README.md`
|
||||||
|
- [ ] Numero de issue es consecutivo (sin saltos ni duplicados)
|
||||||
|
- [ ] Si es multi-issue: sub-issues creados, feature flag en `dev/feature_flags.json`, seccion de desglose en issue principal
|
||||||
|
|
||||||
|
### 9. Reportar al usuario
|
||||||
|
|
||||||
|
Mostrar resumen:
|
||||||
|
- Numero y titulo del issue
|
||||||
|
- Si fue desglosado: listar sub-issues con su alcance
|
||||||
|
- Recordar: usar `/fix-issue <NNNN>` (o `/fix-issue <NNNN>a`, `<NNNN>b`, etc.) para implementar
|
||||||
|
|
||||||
|
## Reglas criticas
|
||||||
|
|
||||||
|
- Seguir `create_issue.md` de forma estricta
|
||||||
|
- **Patron pure core / impure shell**: toda feature debe explicar que va en `pkg/` vs `shell/`
|
||||||
|
- **Tareas atomicas**: cada tarea debe ser implementable de forma independiente
|
||||||
|
- **Numeracion continua**: nunca reusar numeros
|
||||||
|
- **Estado**: issues nuevos siempre `pendiente`
|
||||||
|
- **Issues grandes**: desglosar en sub-issues con feature flags, nunca dejar una rama abierta por dias
|
||||||
|
- **Feature flag != WIP**: un flag protege codigo terminado y testeado, no codigo a medias
|
||||||
|
- **No commitear**: este comando solo crea archivos en `dev/issues/`. No hace commits ni crea ramas
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
# Command: fix issue
|
||||||
|
|
||||||
|
Ejecuta de punta a punta el flujo de implementacion/cierre de un issue siguiendo **estrictamente** la regla `fix_issue.md`.
|
||||||
|
|
||||||
|
## Inputs
|
||||||
|
|
||||||
|
Se necesita el issue objetivo. Si no se proporciona, preguntar.
|
||||||
|
|
||||||
|
- `issue`: numero o nombre (ej: `0010` o `0010-access-control`)
|
||||||
|
|
||||||
|
## Flujo obligatorio
|
||||||
|
|
||||||
|
1. Resolver el issue objetivo:
|
||||||
|
|
||||||
|
- Si viene solo numero (`0010`), buscar `dev/issues/0010-*.md`.
|
||||||
|
- Si viene slug completo (`0010-access-control`), usar `dev/issues/0010-access-control.md`.
|
||||||
|
- Si no existe en `dev/issues/`, **STOP** e informar al usuario.
|
||||||
|
- Si ya esta en `dev/issues/completed/`, **STOP** e informar al usuario.
|
||||||
|
|
||||||
|
2. Leer completo el issue y extraer:
|
||||||
|
|
||||||
|
- objetivo
|
||||||
|
- tareas/fases
|
||||||
|
- arquitectura y limites (pure core / impure shell)
|
||||||
|
|
||||||
|
3. Crear rama de trabajo (inline, sin invocar `/git-branch`):
|
||||||
|
|
||||||
|
Verificar la rama actual:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git branch --show-current
|
||||||
|
```
|
||||||
|
|
||||||
|
- Si ya estamos en `issue/<NNNN>-<slug>` que coincide con el issue → continuar directamente a paso 4.
|
||||||
|
- Si estamos en `master` o cualquier otra rama → crear la rama:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git checkout master
|
||||||
|
git pull --rebase
|
||||||
|
git checkout -b issue/<NNNN>-<slug>
|
||||||
|
```
|
||||||
|
|
||||||
|
Nunca trabajar directamente en `master`.
|
||||||
|
|
||||||
|
4. Planificar con `TodoWrite`:
|
||||||
|
|
||||||
|
- Crear plan basado en las tareas del issue.
|
||||||
|
- Respetar el orden de fases.
|
||||||
|
- Incluir siempre una tarea de tests.
|
||||||
|
|
||||||
|
5. Implementar el issue completo:
|
||||||
|
|
||||||
|
- Ejecutar tareas en orden.
|
||||||
|
- Respetar pure core / impure shell (`pkg/` puro, `shell/` impuro).
|
||||||
|
- Compilar frecuentemente: `go build -tags goolm ./...`.
|
||||||
|
- Marcar progreso en `TodoWrite` al completar cada bloque.
|
||||||
|
|
||||||
|
6. Tests obligatorios:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go test -tags goolm ./...
|
||||||
|
```
|
||||||
|
|
||||||
|
- Si falla, corregir antes de continuar.
|
||||||
|
- No cerrar el issue sin tests pasando.
|
||||||
|
|
||||||
|
7. Feature flags (si aplica):
|
||||||
|
|
||||||
|
- Evaluar si es feature multi-issue o despliegue gradual.
|
||||||
|
- Si aplica, actualizar `dev/feature_flags.json` en el commit correspondiente.
|
||||||
|
- No usar flags para esconder codigo incompleto.
|
||||||
|
|
||||||
|
8. Cerrar el issue al terminar:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mv dev/issues/<NNNN>-<slug>.md dev/issues/completed/
|
||||||
|
```
|
||||||
|
|
||||||
|
Actualizar `dev/issues/README.md`:
|
||||||
|
|
||||||
|
- Link a `completed/<NNNN>-<slug>.md`
|
||||||
|
- Estado a `completado`
|
||||||
|
|
||||||
|
9. Integrar/publicar con `/git-push`:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/git-push
|
||||||
|
```
|
||||||
|
|
||||||
|
## Reglas criticas
|
||||||
|
|
||||||
|
- Seguir `fix_issue.md` de forma estricta.
|
||||||
|
- No saltear tareas del issue.
|
||||||
|
- No hacer commits WIP.
|
||||||
|
- Commits atomicos por bloque logico (`feat:`, `fix:`, `test:`, `docs:`, `refactor:`, `chore:`).
|
||||||
|
- Siempre usar `-tags goolm` en build/test.
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
# Command: git branch (TBD)
|
||||||
|
|
||||||
|
Crea una rama de trabajo. **Nunca trabajar directamente en master.**
|
||||||
|
|
||||||
|
Soporta dos tipos de rama:
|
||||||
|
- `issue/<NNNN>-<slug>` — para implementar un issue existente de `dev/issues/`
|
||||||
|
- `quick/<slug>` — para cambios pequeños sin issue asociado (fixes, config, docs, etc.)
|
||||||
|
|
||||||
|
## Inputs
|
||||||
|
|
||||||
|
Preguntar al usuario si el cambio esta asociado a un issue o no.
|
||||||
|
|
||||||
|
### Si es un issue:
|
||||||
|
- `issue_number`: numero de 4 digitos (e.g. `0020`)
|
||||||
|
- `slug`: nombre corto separado por guiones (e.g. `hot-reload`)
|
||||||
|
|
||||||
|
### Si es un cambio rapido (sin issue):
|
||||||
|
- `slug`: nombre corto descriptivo separado por guiones (e.g. `fix-typo-readme`)
|
||||||
|
|
||||||
|
## Flujo obligatorio
|
||||||
|
|
||||||
|
1. Verificar que estamos en master y limpio:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git branch --show-current
|
||||||
|
git status --short
|
||||||
|
```
|
||||||
|
|
||||||
|
Si no estamos en master, cambiar primero:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git checkout master
|
||||||
|
```
|
||||||
|
|
||||||
|
Si hay cambios sin commitear, **avisar al usuario** y no continuar hasta resolver.
|
||||||
|
|
||||||
|
2. Actualizar master desde remoto:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git pull --rebase
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Crear la rama y cambiar a ella:
|
||||||
|
|
||||||
|
**Para issues:**
|
||||||
|
```bash
|
||||||
|
git checkout -b issue/<issue_number>-<slug>
|
||||||
|
```
|
||||||
|
Ejemplo: `git checkout -b issue/0013-hot-reload`
|
||||||
|
|
||||||
|
**Para cambios rapidos:**
|
||||||
|
```bash
|
||||||
|
git checkout -b quick/<slug>
|
||||||
|
```
|
||||||
|
Ejemplo: `git checkout -b quick/fix-typo-readme`
|
||||||
|
|
||||||
|
4. Confirmar al usuario:
|
||||||
|
|
||||||
|
```
|
||||||
|
Rama `<nombre-rama>` creada desde master actualizado.
|
||||||
|
Puedes empezar a trabajar. Cuando termines, usa `/git-push` para integrar a master.
|
||||||
|
```
|
||||||
|
|
||||||
|
## Convenciones
|
||||||
|
|
||||||
|
- **Formato de rama issue**: `issue/<NNNN>-<slug>` (siempre 4 digitos)
|
||||||
|
- **Formato de rama quick**: `quick/<slug>` (sin numero)
|
||||||
|
- **Ramas cortas**: idealmente horas, no dias
|
||||||
|
- **Una rama por issue**: no mezclar issues en la misma rama
|
||||||
|
- **Nunca pushear la rama al remoto**: el push se hace desde master despues del merge
|
||||||
|
- **No rebase interactivo**: si los commits son limpios desde el inicio, no reescribir historia
|
||||||
|
- **No commits WIP**: cada commit en la rama debe ser atomico y con mensaje real (ver convencion en `/git-push`)
|
||||||
|
|
||||||
|
## Features multi-issue
|
||||||
|
|
||||||
|
Para features que no caben en una sola rama, usar sub-issues con sufijo letra:
|
||||||
|
|
||||||
|
```
|
||||||
|
issue/0015a-telegram-types
|
||||||
|
issue/0015b-telegram-client
|
||||||
|
issue/0015c-telegram-listener
|
||||||
|
issue/0015d-telegram-enable
|
||||||
|
```
|
||||||
|
|
||||||
|
Cada sub-rama sigue el mismo flujo: crear → implementar → merge --no-ff → delete.
|
||||||
|
El codigo parcial se protege con **feature flags** en `dev/feature_flags.json` (no con commits WIP).
|
||||||
@@ -0,0 +1,157 @@
|
|||||||
|
# Command: git push
|
||||||
|
|
||||||
|
Integra cambios a master y publica. Soporta ramas `issue/*` y `quick/*`.
|
||||||
|
|
||||||
|
## Flujo obligatorio
|
||||||
|
|
||||||
|
### 1. Verificar rama actual y estado
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git branch --show-current
|
||||||
|
git status --short
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Si estamos en una rama `issue/*` o `quick/*`
|
||||||
|
|
||||||
|
Continuar directamente al paso 2.
|
||||||
|
|
||||||
|
#### Si estamos en `master` con cambios pendientes
|
||||||
|
|
||||||
|
Crear una rama automaticamente antes de continuar:
|
||||||
|
|
||||||
|
1. Preguntar al usuario: **¿Este cambio esta asociado a un issue existente?**
|
||||||
|
2. **Si es un issue**: pedir el numero y slug, crear rama `issue/<NNNN>-<slug>`.
|
||||||
|
3. **Si NO es un issue**: pedir un slug descriptivo, crear rama `quick/<slug>`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Para issues:
|
||||||
|
git checkout -b issue/<NNNN>-<slug>
|
||||||
|
# Para cambios rapidos:
|
||||||
|
git checkout -b quick/<slug>
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Continuar al paso 2 con los cambios ya en la rama nueva.
|
||||||
|
|
||||||
|
**IMPORTANTE**: No inventar numeros de issue. Solo usar `issue/` si el issue existe en `dev/issues/`.
|
||||||
|
|
||||||
|
#### Si estamos en `master` sin cambios
|
||||||
|
|
||||||
|
**STOP**: no hay nada que publicar.
|
||||||
|
|
||||||
|
### 2. Revisar cambios y crear commits por bloque
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git status --short
|
||||||
|
git diff --stat
|
||||||
|
git diff
|
||||||
|
```
|
||||||
|
|
||||||
|
Crear commits **atomicos por bloque logico**. Cada commit agrupa cambios de la misma naturaleza:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add <archivos_del_bloque_1>
|
||||||
|
git commit -m "<tipo>: <resumen breve>" -m "Descripcion larga en espanol explicando que cambia, por que se hizo, impacto esperado y alcance del bloque."
|
||||||
|
|
||||||
|
git add <archivos_del_bloque_2>
|
||||||
|
git commit -m "<tipo>: <resumen breve>" -m "Descripcion larga en espanol."
|
||||||
|
```
|
||||||
|
|
||||||
|
**Reglas criticas de commits:**
|
||||||
|
- **No WIP**: nunca commitear "wip", "tmp", "fix fix" ni codigo a medias. Cada commit debe ser atomico y completo.
|
||||||
|
- **No mezclar tipos**: no combinar `feat:` + `test:` en un mismo commit. Separar por bloque logico.
|
||||||
|
- **No squash**: los commits individuales se preservan en master via `--no-ff`. Usar `git log --first-parent master` para ver solo merge commits.
|
||||||
|
- **No rebase interactivo**: si los commits ya son limpios, no reescribir historia.
|
||||||
|
|
||||||
|
### 3. Ejecutar tests
|
||||||
|
|
||||||
|
**Obligatorio antes de mergear.** Si el proyecto tiene tests, ejecutarlos:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go test -tags goolm ./...
|
||||||
|
```
|
||||||
|
|
||||||
|
- Si los tests **fallan** → **STOP**: corregir antes de continuar. No mergear codigo roto.
|
||||||
|
- Si los tests **pasan** → continuar al paso 4.
|
||||||
|
- Si no hay tests aplicables (e.g. solo cambios de docs/config) → indicar al usuario y continuar.
|
||||||
|
|
||||||
|
### 4. Evaluar feature flags
|
||||||
|
|
||||||
|
Feature flags se usan cuando el issue es **parte de una feature multi-issue** o el cambio tiene riesgo y necesita poder desactivarse. **Feature flag ≠ WIP** — un flag protege codigo terminado y testeado, no codigo a medias.
|
||||||
|
|
||||||
|
Si se modifico `dev/feature_flags.json` o si los cambios son parte de una feature que se despliega en fases:
|
||||||
|
|
||||||
|
1. Verificar que `dev/feature_flags.json` existe y esta actualizado.
|
||||||
|
2. Confirmar que el flag correspondiente tiene el estado correcto (`enabled: true/false`).
|
||||||
|
3. Incluir el archivo en el commit correspondiente (no crear commit separado solo para flags).
|
||||||
|
|
||||||
|
Si el issue es autocontenido (se completa en esta rama), no necesita flag. Saltar este paso.
|
||||||
|
|
||||||
|
### 5. Actualizar master y hacer merge --no-ff
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git checkout master
|
||||||
|
git pull --rebase
|
||||||
|
git merge --no-ff <rama> -m "merge: <rama> — <titulo breve>"
|
||||||
|
```
|
||||||
|
|
||||||
|
El merge commit debe tener formato:
|
||||||
|
- Titulo: `merge: <rama> — <descripcion corta>`
|
||||||
|
- Cuerpo (opcional): resumen de lo que entra
|
||||||
|
|
||||||
|
Ejemplos:
|
||||||
|
- `merge: issue/0021-threads-default-config — habilitar threads en agentes`
|
||||||
|
- `merge: quick/fix-typo-readme — corregir typo en README`
|
||||||
|
|
||||||
|
Si hay conflictos durante el merge:
|
||||||
|
1. Resolver los conflictos
|
||||||
|
2. `git add` los archivos resueltos
|
||||||
|
3. `git commit` (sin -m, para mantener el mensaje de merge)
|
||||||
|
|
||||||
|
### 6. Push a remoto
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git push
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7. Limpiar rama local
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git branch -d <rama>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8. Confirmar al usuario
|
||||||
|
|
||||||
|
```
|
||||||
|
Rama `<rama>` integrada a master y publicada.
|
||||||
|
Rama local eliminada.
|
||||||
|
```
|
||||||
|
|
||||||
|
## Convencion de commits
|
||||||
|
|
||||||
|
- `feat:` nueva funcionalidad
|
||||||
|
- `fix:` correccion de error
|
||||||
|
- `refactor:` cambio estructural sin cambio funcional
|
||||||
|
- `docs:` documentacion
|
||||||
|
- `chore:` mantenimiento
|
||||||
|
- `test:` tests nuevos o modificados
|
||||||
|
- `merge:` commit de merge (generado por --no-ff)
|
||||||
|
|
||||||
|
## Regla de mensajes
|
||||||
|
|
||||||
|
- El titulo (`-m` corto) debe resumir el bloque.
|
||||||
|
- El cuerpo (`-m` largo) debe estar en espanol y explicar:
|
||||||
|
- que se cambio,
|
||||||
|
- por que se cambio,
|
||||||
|
- que impacto tiene,
|
||||||
|
- que no se toco.
|
||||||
|
|
||||||
|
## Checklist rapido
|
||||||
|
|
||||||
|
- [ ] Todos los cambios estan commiteados en una rama `issue/*` o `quick/*`.
|
||||||
|
- [ ] Se separaron cambios distintos en commits diferentes.
|
||||||
|
- [ ] Cada commit tiene descripcion larga en espanol.
|
||||||
|
- [ ] Tests ejecutados y pasando (o no aplican).
|
||||||
|
- [ ] Feature flags evaluados (o no aplican).
|
||||||
|
- [ ] `git merge --no-ff` ejecutado desde master.
|
||||||
|
- [ ] `git push` ejecutado correctamente.
|
||||||
|
- [ ] Rama local eliminada.
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
---
|
|
||||||
name: auto-create
|
|
||||||
description: Crea un issue nuevo e integra automáticamente SIN pedir confirmación
|
|
||||||
disable-model-invocation: true
|
|
||||||
user-invocable: true
|
|
||||||
allowed-tools: Bash, Read, Write, Edit
|
|
||||||
---
|
|
||||||
|
|
||||||
# auto-create
|
|
||||||
|
|
||||||
Crea un issue nuevo y lo integra automáticamente **sin pedir confirmación**.
|
|
||||||
|
|
||||||
## Sintaxis
|
|
||||||
|
|
||||||
```bash
|
|
||||||
/auto-create
|
|
||||||
```
|
|
||||||
|
|
||||||
## Diferencia con /create-issue
|
|
||||||
|
|
||||||
Este comando NO pausa para confirmación. Solicita datos pero integra automáticamente.
|
|
||||||
|
|
||||||
## Flujo
|
|
||||||
|
|
||||||
### 1-7. Crear issue (igual que /create-issue)
|
|
||||||
|
|
||||||
1. Determinar número
|
|
||||||
2. Solicitar inputs (titulo, descripción)
|
|
||||||
3. Generar slug
|
|
||||||
4. Evaluar tamaño
|
|
||||||
5. Crear desde template
|
|
||||||
6. Feature flag (si aplica)
|
|
||||||
7. Actualizar índice
|
|
||||||
|
|
||||||
**Sin confirmación** - continuar directamente.
|
|
||||||
|
|
||||||
### 8. Integración automática
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git checkout master
|
|
||||||
git pull --rebase
|
|
||||||
git checkout -b quick/create-issue-<NNNN>
|
|
||||||
|
|
||||||
# Commit
|
|
||||||
git add dev/issues/<NNNN>*.md dev/issues/README.md
|
|
||||||
git commit -m "docs: crear issue <NNNN>-<slug>"
|
|
||||||
|
|
||||||
# Si multi-issue, commit de feature flag
|
|
||||||
git add dev/feature_flags.json
|
|
||||||
git commit -m "feat: agregar feature flag <nombre>"
|
|
||||||
|
|
||||||
# Tests (si aplican)
|
|
||||||
go test -tags goolm ./...
|
|
||||||
|
|
||||||
# Merge
|
|
||||||
git checkout master
|
|
||||||
git merge --no-ff quick/create-issue-<NNNN>
|
|
||||||
git push
|
|
||||||
git branch -d quick/create-issue-<NNNN>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 9. Mostrar resultado
|
|
||||||
|
|
||||||
```
|
|
||||||
Issue <NNNN>-<slug> creado e integrado automáticamente
|
|
||||||
|
|
||||||
Para implementar:
|
|
||||||
/fix-issue <NNNN>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Convenciones
|
|
||||||
|
|
||||||
- Sin confirmación
|
|
||||||
- Mismo formato que /create-issue
|
|
||||||
- Trunk-based con rama quick/
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
---
|
|
||||||
name: auto-fix
|
|
||||||
description: Implementa un issue completo automáticamente SIN pedir confirmación
|
|
||||||
argument-hint: <NNNN>
|
|
||||||
disable-model-invocation: true
|
|
||||||
user-invocable: true
|
|
||||||
allowed-tools: Bash, Read, Write, Edit, TodoWrite
|
|
||||||
---
|
|
||||||
|
|
||||||
# auto-fix
|
|
||||||
|
|
||||||
Implementa un issue completo automáticamente **sin pedir confirmación** antes de integrar.
|
|
||||||
|
|
||||||
## Sintaxis
|
|
||||||
|
|
||||||
```bash
|
|
||||||
/auto-fix <NNNN>
|
|
||||||
/auto-fix <NNNN>-<slug>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Diferencia con /fix-issue
|
|
||||||
|
|
||||||
Este comando NO pausa para confirmación. Ejecuta todo el flujo automáticamente.
|
|
||||||
|
|
||||||
**Usar cuando:** estés completamente seguro de que el issue puede implementarse automáticamente.
|
|
||||||
|
|
||||||
## Flujo
|
|
||||||
|
|
||||||
### 1-8. Implementar (igual que /fix-issue)
|
|
||||||
|
|
||||||
1. Resolver issue objetivo
|
|
||||||
2. Leer issue completo
|
|
||||||
3. Crear rama `issue/<NNNN>-<slug>`
|
|
||||||
4. Planificar con TodoWrite
|
|
||||||
5. Implementar completo
|
|
||||||
6. Tests obligatorios
|
|
||||||
7. Feature flags (si aplica)
|
|
||||||
8. Cerrar issue
|
|
||||||
|
|
||||||
**Sin confirmación** - continuar directamente.
|
|
||||||
|
|
||||||
### 9. Integración automática
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git checkout master
|
|
||||||
git pull --rebase
|
|
||||||
go test -tags goolm ./... # verificación final
|
|
||||||
git merge --no-ff issue/<NNNN>-<slug> -m "merge: issue/<NNNN>-<slug>"
|
|
||||||
git push
|
|
||||||
git branch -d issue/<NNNN>-<slug>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 10. Mostrar resultado
|
|
||||||
|
|
||||||
```
|
|
||||||
Issue <NNNN> completado e integrado automáticamente
|
|
||||||
|
|
||||||
Commits integrados: N
|
|
||||||
Tests: pasando
|
|
||||||
Issue: movido a completed/
|
|
||||||
|
|
||||||
NOTA: Integración automática sin confirmación.
|
|
||||||
```
|
|
||||||
|
|
||||||
## Convenciones
|
|
||||||
|
|
||||||
- Sin confirmación (diferencia clave)
|
|
||||||
- Misma calidad que /fix-issue
|
|
||||||
- STOP si tests fallan
|
|
||||||
|
|
||||||
## Reglas
|
|
||||||
|
|
||||||
- NO pedir confirmación
|
|
||||||
- MISMA calidad que /fix-issue
|
|
||||||
- STOP si tests fallan (no integrar código roto)
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
---
|
|
||||||
name: cleanup-worktrees
|
|
||||||
description: Limpia worktrees y ramas locales después de merge
|
|
||||||
argument-hint: <issue_number> | --all
|
|
||||||
disable-model-invocation: true
|
|
||||||
user-invocable: true
|
|
||||||
allowed-tools: Bash, Read
|
|
||||||
---
|
|
||||||
|
|
||||||
# cleanup-worktrees
|
|
||||||
|
|
||||||
Elimina worktrees y sus ramas locales asociadas después de haber sido mergeadas.
|
|
||||||
|
|
||||||
## Sintaxis
|
|
||||||
|
|
||||||
```bash
|
|
||||||
/cleanup-worktrees <NNNN> # Limpiar worktree específico
|
|
||||||
/cleanup-worktrees --all # Limpiar todos
|
|
||||||
```
|
|
||||||
|
|
||||||
## Flujo
|
|
||||||
|
|
||||||
### 1. Validar argumentos
|
|
||||||
|
|
||||||
- Número de issue (4 dígitos): limpiar ese worktree
|
|
||||||
- `--all`: limpiar todos en `worktrees/`
|
|
||||||
|
|
||||||
### 2. Determinar worktrees a limpiar
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Para issue específica
|
|
||||||
WORKTREE_PATH="worktrees/issue-$ISSUE_NUM"
|
|
||||||
|
|
||||||
# Para --all
|
|
||||||
find worktrees -maxdepth 1 -type d -name "issue-*"
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Confirmar con usuario
|
|
||||||
|
|
||||||
```
|
|
||||||
Se eliminarán:
|
|
||||||
- worktrees/issue-0003 (rama: quick/fix-issue-0003)
|
|
||||||
|
|
||||||
¿Continuar? (y/N):
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. Limpiar cada worktree
|
|
||||||
|
|
||||||
Para cada uno:
|
|
||||||
1. Verificar si rama fue mergeada
|
|
||||||
2. Si NO mergeada: advertir y preguntar
|
|
||||||
3. Eliminar worktree: `git worktree remove <path> --force`
|
|
||||||
4. Eliminar rama: `git branch -D <branch>`
|
|
||||||
|
|
||||||
### 5. Reportar resultado
|
|
||||||
|
|
||||||
```
|
|
||||||
Limpieza completada
|
|
||||||
|
|
||||||
Worktrees restantes:
|
|
||||||
(ninguno)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Convenciones
|
|
||||||
|
|
||||||
- Nomenclatura worktrees: `worktrees/issue-NNNN`
|
|
||||||
- Nomenclatura ramas: `quick/fix-issue-NNNN`
|
|
||||||
- Confirmación interactiva siempre
|
|
||||||
|
|
||||||
## Reglas
|
|
||||||
|
|
||||||
- SIEMPRE verificar merge antes de eliminar
|
|
||||||
- NUNCA eliminar sin confirmación
|
|
||||||
- SIEMPRE usar --force en worktree remove
|
|
||||||
@@ -1,439 +0,0 @@
|
|||||||
---
|
|
||||||
name: create-agent
|
|
||||||
description: Crea un nuevo agente especializado en .claude/agents/ con su SKILL.md y estructura completa
|
|
||||||
argument-hint: [nombre]
|
|
||||||
disable-model-invocation: true
|
|
||||||
user-invocable: true
|
|
||||||
allowed-tools: Bash, Read, Write, Edit, AskUserQuestion
|
|
||||||
---
|
|
||||||
|
|
||||||
# create-agent
|
|
||||||
|
|
||||||
Crea un nuevo agente especializado en `.claude/agents/` con archivo `SKILL.md` obligatorio siguiendo la estructura oficial de Claude Code.
|
|
||||||
|
|
||||||
## Sintaxis
|
|
||||||
|
|
||||||
```bash
|
|
||||||
/create-agent [nombre]
|
|
||||||
/create-agent api-client
|
|
||||||
/create-agent cloud-deploy
|
|
||||||
```
|
|
||||||
|
|
||||||
## Precondiciones
|
|
||||||
|
|
||||||
- [ ] Carpeta `.claude/agents/` existe
|
|
||||||
- [ ] No existe agente con el mismo nombre
|
|
||||||
- [ ] Nombre cumple convenciones (minúsculas, guiones)
|
|
||||||
|
|
||||||
## Flujo
|
|
||||||
|
|
||||||
### 1. Validar nombre
|
|
||||||
|
|
||||||
- Solo minúsculas, números y guiones
|
|
||||||
- No nombres reservados (help, clear, exit)
|
|
||||||
- Máximo 64 caracteres
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ls -d .claude/agents/*/ 2>/dev/null | xargs -n1 basename | grep -E "^${nombre}$"
|
|
||||||
```
|
|
||||||
|
|
||||||
Si existe, STOP.
|
|
||||||
|
|
||||||
### 2. Solicitar inputs usando AskUserQuestion
|
|
||||||
|
|
||||||
Usar `AskUserQuestion` para obtener:
|
|
||||||
|
|
||||||
#### Input 1: Información básica
|
|
||||||
- **nombre**: minúsculas y guiones (ej: `api-client`)
|
|
||||||
- **descripcion**: qué hace el agente y cuándo invocarlo (1-2 frases claras)
|
|
||||||
|
|
||||||
#### Input 2: Configuración técnica
|
|
||||||
- **model**: Modelo Claude a usar
|
|
||||||
- `sonnet` (default): Balance costo/capacidad
|
|
||||||
- `opus`: Tareas complejas que requieren máximo razonamiento
|
|
||||||
- `haiku`: Tareas simples y rápidas
|
|
||||||
|
|
||||||
- **tools**: Herramientas necesarias (separadas por coma)
|
|
||||||
- Default: `Read, Write, Bash, Glob, Grep, Edit`
|
|
||||||
- Opcionales: `WebFetch, WebSearch, NotebookEdit`
|
|
||||||
|
|
||||||
#### Input 3: Configuración de proyecto
|
|
||||||
- **gestiona_repo**: ¿Gestiona un repositorio local?
|
|
||||||
- `si`: Crear carpeta en `~/.local_agentes/`
|
|
||||||
- `no`: Solo definición de agente
|
|
||||||
|
|
||||||
- **usa_mcp**: ¿Usa MCP servers? (gitea, sqlite, etc)
|
|
||||||
- `si`: Solicitar configuración de MCP
|
|
||||||
- `no`: Omitir mcpServers
|
|
||||||
|
|
||||||
#### Input 4: MCP Servers (si usa_mcp = si)
|
|
||||||
Preguntar qué MCP servers necesita:
|
|
||||||
- `gitea`: Gestión de repositorios Gitea
|
|
||||||
- `sqlite`: Bases de datos SQLite
|
|
||||||
- `filesystem`: Sistema de archivos
|
|
||||||
- `otro`: Configuración personalizada
|
|
||||||
|
|
||||||
#### Input 5: Documentación
|
|
||||||
- **rol**: Rol del agente (ej: "Eres un experto en...")
|
|
||||||
- **capacidades**: Lista de capacidades principales
|
|
||||||
- **flujo_trabajo**: Descripción del flujo de trabajo típico
|
|
||||||
- **ejemplos_uso**: Ejemplos de cuándo invocar al agente
|
|
||||||
|
|
||||||
### 3. Crear carpeta del agente
|
|
||||||
|
|
||||||
```bash
|
|
||||||
mkdir -p .claude/agents/${nombre}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. Crear carpeta local (si gestiona_repo = si)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
mkdir -p ~/.local_agentes/${nombre}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5. Generar frontmatter YAML
|
|
||||||
|
|
||||||
Estructura base:
|
|
||||||
```yaml
|
|
||||||
---
|
|
||||||
name: ${nombre}
|
|
||||||
description: ${descripcion}
|
|
||||||
model: ${model}
|
|
||||||
tools: ${tools}
|
|
||||||
mcpServers: # Solo si usa_mcp = si
|
|
||||||
- ${mcp_config}
|
|
||||||
---
|
|
||||||
```
|
|
||||||
|
|
||||||
### 6. Generar SKILL.md completo
|
|
||||||
|
|
||||||
Template oficial de agente:
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
---
|
|
||||||
name: ${nombre}
|
|
||||||
description: ${descripcion}
|
|
||||||
model: ${model}
|
|
||||||
tools: ${tools}
|
|
||||||
${mcp_servers_section}
|
|
||||||
---
|
|
||||||
|
|
||||||
# Agente ${nombre}
|
|
||||||
|
|
||||||
${rol}
|
|
||||||
|
|
||||||
## Tu entorno
|
|
||||||
|
|
||||||
${descripcion_entorno}
|
|
||||||
|
|
||||||
## Capacidades principales
|
|
||||||
|
|
||||||
${capacidades}
|
|
||||||
|
|
||||||
## Flujo de trabajo
|
|
||||||
|
|
||||||
${flujo_trabajo}
|
|
||||||
|
|
||||||
## Templates disponibles
|
|
||||||
|
|
||||||
${templates_codigo}
|
|
||||||
|
|
||||||
## Integración con otros agentes
|
|
||||||
|
|
||||||
${integracion}
|
|
||||||
|
|
||||||
## Ejemplos de uso
|
|
||||||
|
|
||||||
${ejemplos_uso}
|
|
||||||
|
|
||||||
## Comandos útiles
|
|
||||||
|
|
||||||
${comandos}
|
|
||||||
|
|
||||||
## Notas y convenciones
|
|
||||||
|
|
||||||
${notas}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 7. Templates de MCP Servers
|
|
||||||
|
|
||||||
#### Gitea MCP
|
|
||||||
```yaml
|
|
||||||
mcpServers:
|
|
||||||
- gitea:
|
|
||||||
type: stdio
|
|
||||||
command: gitea-mcp
|
|
||||||
args:
|
|
||||||
- -t
|
|
||||||
- stdio
|
|
||||||
- --host
|
|
||||||
- "${GITEA_URL}"
|
|
||||||
- --token
|
|
||||||
- "${GITEA_TOKEN}"
|
|
||||||
```
|
|
||||||
|
|
||||||
#### SQLite MCP
|
|
||||||
```yaml
|
|
||||||
mcpServers:
|
|
||||||
- sqlite:
|
|
||||||
type: stdio
|
|
||||||
command: sqlite-mcp
|
|
||||||
args:
|
|
||||||
- --db
|
|
||||||
- "${DB_PATH}"
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Filesystem MCP
|
|
||||||
```yaml
|
|
||||||
mcpServers:
|
|
||||||
- filesystem:
|
|
||||||
type: stdio
|
|
||||||
command: mcp-server-filesystem
|
|
||||||
args:
|
|
||||||
- --allowed-directories
|
|
||||||
- "${ALLOWED_DIR}"
|
|
||||||
```
|
|
||||||
|
|
||||||
### 8. Mostrar y confirmar
|
|
||||||
|
|
||||||
```
|
|
||||||
Agente creado: ${nombre}
|
|
||||||
Ubicación: .claude/agents/${nombre}/SKILL.md
|
|
||||||
${carpeta_local ? "Carpeta local: ~/.local_agentes/" + nombre : ""}
|
|
||||||
|
|
||||||
Configuración:
|
|
||||||
- Model: ${model}
|
|
||||||
- Tools: ${tools}
|
|
||||||
- MCP: ${usa_mcp ? "Sí" : "No"}
|
|
||||||
- Repositorio local: ${gestiona_repo ? "Sí" : "No"}
|
|
||||||
|
|
||||||
¿Te parece bien?
|
|
||||||
- Si correcto: commit e integrar automáticamente
|
|
||||||
- Si ajustes: edita manualmente antes de integrar
|
|
||||||
```
|
|
||||||
|
|
||||||
### 9. Crear README.md en carpeta local (si gestiona_repo = si)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cat > ~/.local_agentes/${nombre}/README.md <<EOF
|
|
||||||
# ${nombre}
|
|
||||||
|
|
||||||
${descripcion}
|
|
||||||
|
|
||||||
## Estructura del proyecto
|
|
||||||
|
|
||||||
\`\`\`
|
|
||||||
~/.local_agentes/${nombre}/
|
|
||||||
├── README.md
|
|
||||||
├── CLAUDE.md # Instrucciones para Claude
|
|
||||||
└── ... # Archivos del proyecto
|
|
||||||
\`\`\`
|
|
||||||
|
|
||||||
## Sincronización con Gitea
|
|
||||||
|
|
||||||
\`\`\`bash
|
|
||||||
cd ~/.local_agentes/${nombre}
|
|
||||||
git remote add origin \${GITEA_URL}/\${user}/${nombre}.git
|
|
||||||
git push -u origin main
|
|
||||||
\`\`\`
|
|
||||||
|
|
||||||
## Uso
|
|
||||||
|
|
||||||
Invocar con:
|
|
||||||
\`\`\`
|
|
||||||
Hablar con el agente ${nombre} para [tarea]
|
|
||||||
\`\`\`
|
|
||||||
EOF
|
|
||||||
```
|
|
||||||
|
|
||||||
### 10. Ejecutar /git-push
|
|
||||||
|
|
||||||
Si confirma, crear rama `quick/create-agent-${nombre}` e integrar.
|
|
||||||
|
|
||||||
### 11. Verificar disponibilidad
|
|
||||||
|
|
||||||
```
|
|
||||||
Agente "${nombre}" creado e integrado
|
|
||||||
|
|
||||||
El agente está disponible en:
|
|
||||||
.claude/agents/${nombre}/SKILL.md
|
|
||||||
|
|
||||||
${gestiona_repo ? "Carpeta de trabajo:\n ~/.local_agentes/" + nombre : ""}
|
|
||||||
|
|
||||||
Para usar, solicita al usuario:
|
|
||||||
"Trabajar con el agente ${nombre} para [tarea]"
|
|
||||||
|
|
||||||
Configuración:
|
|
||||||
- Model: ${model}
|
|
||||||
- Tools: ${tools}
|
|
||||||
- MCP Servers: ${usa_mcp ? "Sí" : "No"}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Campos del frontmatter de agentes
|
|
||||||
|
|
||||||
| Campo | Descripción | Requerido |
|
|
||||||
|-------|-------------|-----------|
|
|
||||||
| name | Nombre del agente | Sí |
|
|
||||||
| description | Qué hace y cuándo invocarlo | Sí |
|
|
||||||
| model | Model Claude (sonnet, opus, haiku) | Sí |
|
|
||||||
| tools | Herramientas disponibles | Sí |
|
|
||||||
| mcpServers | Servidores MCP (opcional) | No |
|
|
||||||
|
|
||||||
## Estructura de documentación de agentes
|
|
||||||
|
|
||||||
Seguir este orden en el contenido Markdown:
|
|
||||||
|
|
||||||
1. **Título y rol**: Descripción del rol del agente
|
|
||||||
2. **Tu entorno**: Dónde trabaja, qué repositorios gestiona
|
|
||||||
3. **Capacidades principales**: Lista de lo que puede hacer
|
|
||||||
4. **Flujo de trabajo**: Cómo abordar tareas típicas
|
|
||||||
5. **Templates disponibles**: Código de ejemplo
|
|
||||||
6. **Integración con otros agentes**: Cómo colabora con otros
|
|
||||||
7. **Ejemplos de uso**: Cuándo invocar al agente
|
|
||||||
8. **Comandos útiles**: Comandos CLI relevantes
|
|
||||||
9. **Notas y convenciones**: Reglas y mejores prácticas
|
|
||||||
|
|
||||||
## Convenciones
|
|
||||||
|
|
||||||
- Nombres descriptivos con guiones (ej: `api-client`, `cloud-deploy`)
|
|
||||||
- Descripciones claras para invocación automática por Claude
|
|
||||||
- Un agente por dominio/especialización
|
|
||||||
- Documentación completa con ejemplos prácticos
|
|
||||||
- Templates de código cuando sea aplicable
|
|
||||||
|
|
||||||
## Diferencia entre Agentes y Skills
|
|
||||||
|
|
||||||
| Característica | Agente | Skill |
|
|
||||||
|----------------|--------|-------|
|
|
||||||
| Ubicación | `.claude/agents/` | `.claude/skills/` |
|
|
||||||
| Propósito | Experto especializado | Automatización/herramienta |
|
|
||||||
| Invocación | Claude decide cuándo | Usuario con `/nombre` |
|
|
||||||
| Contenido | Conocimiento de dominio | Flujo de trabajo |
|
|
||||||
| Ejemplo | `backend-lib`, `docker` | `git-push`, `create-issue` |
|
|
||||||
|
|
||||||
## Ejemplos de agentes
|
|
||||||
|
|
||||||
### Agente simple (sin repo ni MCP)
|
|
||||||
```yaml
|
|
||||||
---
|
|
||||||
name: code-review
|
|
||||||
description: Agente para revisar código y sugerir mejoras
|
|
||||||
model: sonnet
|
|
||||||
tools: Read, Grep, Glob
|
|
||||||
---
|
|
||||||
|
|
||||||
# Agente Code Review
|
|
||||||
|
|
||||||
Eres un experto en revisión de código...
|
|
||||||
```
|
|
||||||
|
|
||||||
### Agente complejo (con repo y MCP)
|
|
||||||
```yaml
|
|
||||||
---
|
|
||||||
name: api-client
|
|
||||||
description: Agente para generar clientes API desde especificaciones OpenAPI
|
|
||||||
model: sonnet
|
|
||||||
tools: Read, Write, Bash, Glob, Grep, Edit
|
|
||||||
mcpServers:
|
|
||||||
- gitea:
|
|
||||||
type: stdio
|
|
||||||
command: gitea-mcp
|
|
||||||
args:
|
|
||||||
- -t
|
|
||||||
- stdio
|
|
||||||
- --host
|
|
||||||
- "${GITEA_URL}"
|
|
||||||
- --token
|
|
||||||
- "${GITEA_TOKEN}"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Agente API Client
|
|
||||||
|
|
||||||
Eres un experto en generación de clientes API...
|
|
||||||
|
|
||||||
## Tu entorno
|
|
||||||
|
|
||||||
- **Repositorio**: `Bl4cksmith/api-clients` (Gitea)
|
|
||||||
- **Carpeta local**: `~/.local_agentes/api-client`
|
|
||||||
- **Stack**: TypeScript, Go, Python
|
|
||||||
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
## Reglas
|
|
||||||
|
|
||||||
- Validar nombre antes de crear
|
|
||||||
- SKILL.md es obligatorio
|
|
||||||
- Confirmación antes de integrar
|
|
||||||
- Crear carpeta local solo si gestiona_repo = si
|
|
||||||
- MCP servers solo si usa_mcp = si
|
|
||||||
- Documentación completa y con ejemplos
|
|
||||||
|
|
||||||
## Integración con otros agentes
|
|
||||||
|
|
||||||
### Con gitea
|
|
||||||
```bash
|
|
||||||
# Crear repositorio para el agente (si gestiona_repo = si)
|
|
||||||
cd ~/.local_agentes/${nombre}
|
|
||||||
git init
|
|
||||||
git add .
|
|
||||||
git commit -m "Initial commit"
|
|
||||||
# Usar agente gitea para crear repo y push
|
|
||||||
```
|
|
||||||
|
|
||||||
### Con backend-lib / frontend-lib
|
|
||||||
```markdown
|
|
||||||
# En SKILL.md del nuevo agente, documentar integración:
|
|
||||||
|
|
||||||
## Integración con otros agentes
|
|
||||||
|
|
||||||
### Con backend-lib (DevFactory)
|
|
||||||
- Usar DevFactory para estructuras funcionales Go
|
|
||||||
- Integrar via go.work
|
|
||||||
|
|
||||||
### Con frontend-lib
|
|
||||||
- Usar Frontend_Library para componentes React
|
|
||||||
- Integrar via pnpm link
|
|
||||||
```
|
|
||||||
|
|
||||||
## Variables dinámicas
|
|
||||||
|
|
||||||
| Variable | Descripción |
|
|
||||||
|----------|-------------|
|
|
||||||
| ${nombre} | Nombre del agente |
|
|
||||||
| ${descripcion} | Descripción del agente |
|
|
||||||
| ${model} | Model Claude |
|
|
||||||
| ${tools} | Herramientas disponibles |
|
|
||||||
| ${CLAUDE_SKILL_DIR} | Ruta del skill |
|
|
||||||
|
|
||||||
## Flujo completo de ejemplo
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Usuario invoca
|
|
||||||
/create-agent api-client
|
|
||||||
|
|
||||||
# Skill valida nombre
|
|
||||||
✓ Nombre válido
|
|
||||||
|
|
||||||
# Skill pregunta configuración con AskUserQuestion
|
|
||||||
? Descripción: Agente para generar clientes API desde OpenAPI
|
|
||||||
? Model: sonnet
|
|
||||||
? Tools: Read, Write, Bash, Glob, Grep, Edit
|
|
||||||
? ¿Gestiona repositorio?: Sí
|
|
||||||
? ¿Usa MCP?: Sí
|
|
||||||
? MCP servers: gitea
|
|
||||||
|
|
||||||
# Skill crea estructura
|
|
||||||
✓ Carpeta creada: .claude/agents/api-client/
|
|
||||||
✓ Carpeta local creada: ~/.local_agentes/api-client/
|
|
||||||
✓ SKILL.md generado
|
|
||||||
✓ README.md generado
|
|
||||||
|
|
||||||
# Skill confirma
|
|
||||||
Agente "api-client" creado
|
|
||||||
|
|
||||||
# Skill integra con git
|
|
||||||
✓ Rama: quick/create-agent-api-client
|
|
||||||
✓ Commit: "feat: crear agente api-client"
|
|
||||||
✓ Push exitoso
|
|
||||||
```
|
|
||||||
@@ -1,99 +0,0 @@
|
|||||||
---
|
|
||||||
name: create-issue
|
|
||||||
description: Crea un issue nuevo en dev/issues/ con confirmación del usuario
|
|
||||||
disable-model-invocation: true
|
|
||||||
user-invocable: true
|
|
||||||
allowed-tools: Bash, Read, Write, Edit
|
|
||||||
---
|
|
||||||
|
|
||||||
# create-issue
|
|
||||||
|
|
||||||
Crea un issue nuevo con estructura completa. Si es grande, lo desglosa en sub-issues con feature flags.
|
|
||||||
|
|
||||||
## Sintaxis
|
|
||||||
|
|
||||||
```bash
|
|
||||||
/create-issue
|
|
||||||
```
|
|
||||||
|
|
||||||
## Precondiciones
|
|
||||||
|
|
||||||
- [ ] Directorio `dev/issues/` existe
|
|
||||||
- [ ] Template `.claude/templates/issue.md` existe
|
|
||||||
|
|
||||||
## Flujo
|
|
||||||
|
|
||||||
### 1. Determinar número del issue
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ls dev/issues/ dev/issues/completed/ | grep -oP '^\d{4}' | sort -rn | head -1
|
|
||||||
```
|
|
||||||
|
|
||||||
Próximo issue = número_más_alto + 1 (formato 4 dígitos)
|
|
||||||
|
|
||||||
### 2. Solicitar inputs
|
|
||||||
|
|
||||||
- `titulo`: título corto y descriptivo
|
|
||||||
- `descripcion`: objetivo de lo que se quiere lograr
|
|
||||||
- `dependencias` (opcional): issues de los que depende
|
|
||||||
|
|
||||||
### 3. Generar slug
|
|
||||||
|
|
||||||
Título → lowercase → palabras separadas por guiones → 2-4 palabras
|
|
||||||
|
|
||||||
### 4. Evaluar tamaño
|
|
||||||
|
|
||||||
**Criterios para sub-issues:**
|
|
||||||
- Toca más de 2 capas (core/ + shell/ + app/)
|
|
||||||
- Requiere más de 3 fases
|
|
||||||
- El usuario lo indica
|
|
||||||
|
|
||||||
**Issue simple:** crear un archivo `dev/issues/<NNNN>-<slug>.md`
|
|
||||||
|
|
||||||
**Issue grande:** crear SOLO sub-issues `<NNNN>a-`, `<NNNN>b-`, etc.
|
|
||||||
|
|
||||||
### 5. Crear desde template
|
|
||||||
|
|
||||||
Usar template en `${CLAUDE_SKILL_DIR}/issue.md` y rellenar todas las secciones:
|
|
||||||
- Metadata, Objetivo, Contexto
|
|
||||||
- Arquitectura, Patrón pure/impure
|
|
||||||
- Tareas, Ejemplo de uso
|
|
||||||
- Criterios de aceptación
|
|
||||||
|
|
||||||
### 6. Feature flag (solo multi-issue)
|
|
||||||
|
|
||||||
Actualizar `dev/feature_flags.json`:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"<nombre-flag>": {
|
|
||||||
"enabled": false,
|
|
||||||
"issue": "<NNNN>",
|
|
||||||
"description": "..."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 7. Actualizar índice
|
|
||||||
|
|
||||||
En `dev/issues/README.md` agregar fila(s).
|
|
||||||
|
|
||||||
### 8. Mostrar y confirmar
|
|
||||||
|
|
||||||
```
|
|
||||||
Issue creado: <NNNN>-<slug>
|
|
||||||
|
|
||||||
¿Te parece bien?
|
|
||||||
- Si es correcto: commit y push automáticamente
|
|
||||||
- Si necesitas ajustes: edita manualmente
|
|
||||||
```
|
|
||||||
|
|
||||||
### 9. Ejecutar /git-push automáticamente
|
|
||||||
|
|
||||||
Si confirma, crear rama `quick/create-issue-<NNNN>` y ejecutar flujo git.
|
|
||||||
|
|
||||||
## Convenciones
|
|
||||||
|
|
||||||
- Numeración continua sin saltos
|
|
||||||
- Estado inicial: pendiente
|
|
||||||
- Issues cortos (horas por rama)
|
|
||||||
- Sub-issues autocontenidos
|
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
# NNNN — [Título de la Issue]
|
|
||||||
|
|
||||||
## Metadata
|
|
||||||
|
|
||||||
| Campo | Valor |
|
|
||||||
|-------|-------|
|
|
||||||
| **ID** | NNNN |
|
|
||||||
| **Estado** | 🟡 pendiente / 🔵 en progreso / ✅ completado / 🔴 bloqueado |
|
|
||||||
| **Prioridad** | alta / media / baja |
|
|
||||||
| **Tipo** | feature / bugfix / refactor / docs / infrastructure |
|
|
||||||
|
|
||||||
## Dependencias
|
|
||||||
|
|
||||||
<!-- Issues que DEBEN estar completadas antes de empezar esta -->
|
|
||||||
|
|
||||||
| ID | Título | Estado | Requerido |
|
|
||||||
|----|--------|--------|-----------|
|
|
||||||
| 0001 | Actualizar nombre del módulo | ✅ | Sí |
|
|
||||||
| 0002 | Implementar core/ | ✅ | Sí |
|
|
||||||
|
|
||||||
**Bloqueada por:** `#0001, #0002`
|
|
||||||
|
|
||||||
**Desbloquea:** `#0006, #0007`
|
|
||||||
|
|
||||||
> **⚠️ VALIDACIÓN AUTOMÁTICA**: Esta issue no puede iniciarse hasta que todas las dependencias estén en estado `✅ completado`.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Objetivo
|
|
||||||
|
|
||||||
[Descripción concisa de qué se quiere lograr en 1-3 oraciones]
|
|
||||||
|
|
||||||
## Contexto
|
|
||||||
|
|
||||||
- [Punto de contexto 1]
|
|
||||||
- [Punto de contexto 2]
|
|
||||||
- [Referencias a otras issues o decisiones previas]
|
|
||||||
|
|
||||||
## Arquitectura
|
|
||||||
|
|
||||||
```
|
|
||||||
[Estructura de archivos afectados]
|
|
||||||
dir/
|
|
||||||
├── file1.go — Descripción
|
|
||||||
├── file2.go — NEW: Nuevo archivo
|
|
||||||
└── file3.go — MODIFY: Modificación
|
|
||||||
```
|
|
||||||
|
|
||||||
### Patrón pure core / impure shell
|
|
||||||
|
|
||||||
- `core/` — [Qué funciones puras se agregan]
|
|
||||||
- `shell/` — [Qué operaciones I/O se implementan]
|
|
||||||
- `app/` — [Cómo se orquesta]
|
|
||||||
|
|
||||||
## Tareas
|
|
||||||
|
|
||||||
### Fase 1: [Nombre de fase]
|
|
||||||
|
|
||||||
- [ ] **1.1** [Descripción detallada de tarea]
|
|
||||||
- [ ] **1.2** [Otra tarea]
|
|
||||||
|
|
||||||
### Fase 2: [Otra fase]
|
|
||||||
|
|
||||||
- [ ] **2.1** [Tarea]
|
|
||||||
- [ ] **2.2** [Tarea]
|
|
||||||
|
|
||||||
### Fase N: Cleanup y docs
|
|
||||||
|
|
||||||
- [ ] Actualizar `README.md` con cambios relevantes
|
|
||||||
- [ ] Actualizar `CLAUDE.md` si hay cambios arquitectónicos
|
|
||||||
- [ ] Ejecutar `go mod tidy`
|
|
||||||
- [ ] Ejecutar `go test ./...`
|
|
||||||
- [ ] Actualizar issue en `dev/issues/README.md`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Ejemplo de uso
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Comandos de ejemplo
|
|
||||||
comando ejemplo arg1 arg2
|
|
||||||
|
|
||||||
# Output esperado:
|
|
||||||
# ✓ Success message
|
|
||||||
```
|
|
||||||
|
|
||||||
```go
|
|
||||||
// Código de ejemplo si aplica
|
|
||||||
package example
|
|
||||||
|
|
||||||
func Example() {}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Decisiones de diseño
|
|
||||||
|
|
||||||
- **Decisión 1**: Razón y trade-offs
|
|
||||||
- **Decisión 2**: Alternativas consideradas y por qué se eligió esta
|
|
||||||
|
|
||||||
## Prerequisitos
|
|
||||||
|
|
||||||
- Issue #NNNN completado
|
|
||||||
- Herramienta X instalada
|
|
||||||
- Configuración Y realizada
|
|
||||||
|
|
||||||
## Riesgos
|
|
||||||
|
|
||||||
- **Riesgo 1**: Descripción del riesgo. **Mitigación**: Cómo se mitigará
|
|
||||||
- **Riesgo 2**: Otro riesgo. **Mitigación**: Plan de mitigación
|
|
||||||
|
|
||||||
## Criterios de aceptación
|
|
||||||
|
|
||||||
- [ ] Todos los tests pasan
|
|
||||||
- [ ] Feature flag agregado en `feature_flags.json`
|
|
||||||
- [ ] Documentación actualizada
|
|
||||||
- [ ] Code review aprobado
|
|
||||||
- [ ] Deployable a main
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Notas de implementación
|
|
||||||
|
|
||||||
[Notas que surjan durante la implementación, decisiones tomadas, problemas encontrados]
|
|
||||||
|
|
||||||
## Referencias
|
|
||||||
|
|
||||||
- [Link a documentación relevante]
|
|
||||||
- [Link a PRs relacionados]
|
|
||||||
- [Link a discusiones]
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
---
|
|
||||||
name: create-repo
|
|
||||||
description: Crea un nuevo subrepo en workspaces/ con estructura core/shell/app
|
|
||||||
disable-model-invocation: true
|
|
||||||
user-invocable: true
|
|
||||||
allowed-tools: Bash, Read, Write
|
|
||||||
---
|
|
||||||
|
|
||||||
# create-repo
|
|
||||||
|
|
||||||
Crea un nuevo workspace (subrepo) con estructura estándar, repo en Gitea, y registro en BD.
|
|
||||||
|
|
||||||
## Prerequisitos
|
|
||||||
|
|
||||||
- Variables: `GITEA_URL` y `GITEA_TOKEN`
|
|
||||||
- Feature flag `workspace_commands` habilitado
|
|
||||||
|
|
||||||
## Flujo interactivo
|
|
||||||
|
|
||||||
### 1. Solicitar inputs
|
|
||||||
|
|
||||||
1. **Nombre**: URL-safe (lowercase, alfanumérico, guiones)
|
|
||||||
2. **Descripción**: texto libre
|
|
||||||
3. **Tipo**: go, data, etl, api
|
|
||||||
4. **¿Privado?**: s/n (default: n)
|
|
||||||
|
|
||||||
### 2. Mostrar resumen y confirmar
|
|
||||||
|
|
||||||
```
|
|
||||||
Resumen:
|
|
||||||
Nombre: my-etl-pipeline
|
|
||||||
Path local: ./workspaces/my-etl-pipeline
|
|
||||||
Gitea: https://gitea.../my-etl-pipeline
|
|
||||||
Tipo: etl
|
|
||||||
Privado: no
|
|
||||||
|
|
||||||
¿Crear repositorio? (s/n):
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Ejecutar creación
|
|
||||||
|
|
||||||
Usa `app.CreateWorkspaceCommand(config, params)`:
|
|
||||||
1. Validar nombre
|
|
||||||
2. Verificar que no existe
|
|
||||||
3. Crear estructura core/shell/app/
|
|
||||||
4. Escribir templates (go.mod, main.go, etc.)
|
|
||||||
5. git init + configurar usuario
|
|
||||||
6. Crear repo en Gitea
|
|
||||||
7. Push inicial
|
|
||||||
8. Registrar en SQLite
|
|
||||||
|
|
||||||
**Rollback automático** si falla cualquier paso.
|
|
||||||
|
|
||||||
### 4. Mostrar resultado
|
|
||||||
|
|
||||||
```
|
|
||||||
Workspace creado: ./workspaces/my-etl-pipeline
|
|
||||||
|
|
||||||
Para trabajar:
|
|
||||||
cd workspaces/my-etl-pipeline
|
|
||||||
```
|
|
||||||
|
|
||||||
## Validación de nombre
|
|
||||||
|
|
||||||
- Solo letras, números y guiones
|
|
||||||
- No empezar/terminar con guión
|
|
||||||
- 2-100 caracteres
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
- "nombre inválido": usar solo lowercase, alfanumérico, guiones
|
|
||||||
- "ya existe": verificar `ls workspaces/` o usar otro nombre
|
|
||||||
- "error Gitea": verificar GITEA_TOKEN
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
---
|
|
||||||
name: fix-issue
|
|
||||||
description: Implementa un issue completo de punta a punta con confirmación
|
|
||||||
argument-hint: <NNNN>
|
|
||||||
disable-model-invocation: true
|
|
||||||
user-invocable: true
|
|
||||||
allowed-tools: Bash, Read, Write, Edit, TodoWrite
|
|
||||||
---
|
|
||||||
|
|
||||||
# fix-issue
|
|
||||||
|
|
||||||
Ejecuta el flujo completo de implementación/cierre de un issue: crear rama, implementar, testear, cerrar, confirmar, integrar.
|
|
||||||
|
|
||||||
## Sintaxis
|
|
||||||
|
|
||||||
```bash
|
|
||||||
/fix-issue <NNNN>
|
|
||||||
/fix-issue <NNNN>-<slug>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Precondiciones
|
|
||||||
|
|
||||||
- [ ] Directorio `dev/issues/` existe
|
|
||||||
- [ ] Directorio `dev/issues/completed/` existe
|
|
||||||
- [ ] Tests configurados
|
|
||||||
- [ ] Working tree limpio
|
|
||||||
|
|
||||||
## Flujo
|
|
||||||
|
|
||||||
### 1. Resolver issue objetivo
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ls dev/issues/<NNNN>-*.md
|
|
||||||
```
|
|
||||||
|
|
||||||
- Si no existe: STOP "Issue no encontrado"
|
|
||||||
- Si ya completado: STOP "Issue ya completado"
|
|
||||||
|
|
||||||
### 2. Leer issue completo
|
|
||||||
|
|
||||||
Extraer: objetivo, tareas, arquitectura, patrón pure/impure, tests.
|
|
||||||
|
|
||||||
### 3. Crear rama de trabajo
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git checkout master
|
|
||||||
git pull --rebase
|
|
||||||
git checkout -b issue/<NNNN>-<slug>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. Planificar con TodoWrite
|
|
||||||
|
|
||||||
Crear plan basado en tareas del issue.
|
|
||||||
|
|
||||||
### 5. Implementar completo
|
|
||||||
|
|
||||||
Para cada tarea:
|
|
||||||
1. Implementar siguiendo patrón pure core / impure shell
|
|
||||||
2. Compilar frecuentemente: `go build -tags goolm ./...`
|
|
||||||
3. Crear commits atómicos durante implementación
|
|
||||||
|
|
||||||
### 6. Tests obligatorios
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go test -tags goolm ./...
|
|
||||||
```
|
|
||||||
|
|
||||||
- Pasan: continuar
|
|
||||||
- Fallan: STOP y corregir
|
|
||||||
|
|
||||||
### 7. Feature flags (si aplica)
|
|
||||||
|
|
||||||
Actualizar `dev/feature_flags.json` si es multi-issue.
|
|
||||||
|
|
||||||
### 8. Cerrar issue
|
|
||||||
|
|
||||||
```bash
|
|
||||||
mv dev/issues/<NNNN>-<slug>.md dev/issues/completed/
|
|
||||||
```
|
|
||||||
|
|
||||||
Actualizar índice en README.md.
|
|
||||||
|
|
||||||
### 9. Mostrar resumen y confirmar
|
|
||||||
|
|
||||||
```
|
|
||||||
Issue <NNNN> completado
|
|
||||||
|
|
||||||
Resumen:
|
|
||||||
- N archivos modificados
|
|
||||||
- N commits realizados
|
|
||||||
- Tests: pasando
|
|
||||||
|
|
||||||
¿Integrar a master?
|
|
||||||
```
|
|
||||||
|
|
||||||
### 10. Ejecutar /git-push
|
|
||||||
|
|
||||||
Si confirma, ejecutar flujo de integración.
|
|
||||||
|
|
||||||
## Convenciones
|
|
||||||
|
|
||||||
- Implementar TODAS las tareas
|
|
||||||
- Commits atómicos durante implementación
|
|
||||||
- Tests obligatorios
|
|
||||||
- Pure core / impure shell
|
|
||||||
|
|
||||||
## Reglas
|
|
||||||
|
|
||||||
- NO saltear tareas
|
|
||||||
- NO commits WIP
|
|
||||||
- SIEMPRE tests antes de cerrar
|
|
||||||
- Confirmación obligatoria antes de integrar
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
---
|
|
||||||
name: git-branch
|
|
||||||
description: Crea una rama de trabajo (issue/* o quick/*). Nunca trabajar directamente en master.
|
|
||||||
argument-hint: <tipo> <args>
|
|
||||||
disable-model-invocation: true
|
|
||||||
user-invocable: true
|
|
||||||
allowed-tools: Bash, Read
|
|
||||||
---
|
|
||||||
|
|
||||||
# git-branch
|
|
||||||
|
|
||||||
Crea una rama de trabajo siguiendo trunk-based development. **Nunca trabajar directamente en master.**
|
|
||||||
|
|
||||||
## Sintaxis
|
|
||||||
|
|
||||||
```bash
|
|
||||||
/git-branch issue <NNNN> <slug>
|
|
||||||
/git-branch quick <slug>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Ejemplos
|
|
||||||
|
|
||||||
```bash
|
|
||||||
/git-branch issue 0013 hot-reload # Crea issue/0013-hot-reload
|
|
||||||
/git-branch quick fix-typo-readme # Crea quick/fix-typo-readme
|
|
||||||
```
|
|
||||||
|
|
||||||
## Precondiciones
|
|
||||||
|
|
||||||
- [ ] Repositorio git válido
|
|
||||||
- [ ] Branch master existe
|
|
||||||
- [ ] Working tree limpio (sin cambios pendientes)
|
|
||||||
|
|
||||||
## Flujo
|
|
||||||
|
|
||||||
### 1. Verificar estado del repositorio
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git branch --show-current
|
|
||||||
git status --short
|
|
||||||
```
|
|
||||||
|
|
||||||
**Si no estamos en master:** `git checkout master`
|
|
||||||
|
|
||||||
**Si hay cambios sin commitear:** STOP y avisar al usuario:
|
|
||||||
```
|
|
||||||
Hay cambios sin commitear. Opciones:
|
|
||||||
1. Commitear: git add . && git commit -m "mensaje"
|
|
||||||
2. Stash: git stash
|
|
||||||
3. Descartar: git reset --hard (peligroso)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Actualizar master desde remoto
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git pull --rebase
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Crear rama según tipo
|
|
||||||
|
|
||||||
**Para issues:**
|
|
||||||
```bash
|
|
||||||
git checkout -b issue/<NNNN>-<slug>
|
|
||||||
```
|
|
||||||
|
|
||||||
**Para cambios rápidos:**
|
|
||||||
```bash
|
|
||||||
git checkout -b quick/<slug>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. Confirmar creación
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git branch --show-current
|
|
||||||
```
|
|
||||||
|
|
||||||
Informar:
|
|
||||||
```
|
|
||||||
Rama `<nombre-rama>` creada desde master actualizado
|
|
||||||
|
|
||||||
Cuando termines:
|
|
||||||
/git-push
|
|
||||||
```
|
|
||||||
|
|
||||||
## Convenciones
|
|
||||||
|
|
||||||
- **Formato issue**: `issue/<NNNN>-<slug>` (4 dígitos)
|
|
||||||
- **Formato quick**: `quick/<slug>`
|
|
||||||
- **Ramas cortas**: horas, no días
|
|
||||||
- **No pushear ramas**: integrar via merge a master
|
|
||||||
- **No underscores**: solo guiones
|
|
||||||
|
|
||||||
## Reglas
|
|
||||||
|
|
||||||
- NUNCA trabajar directamente en master
|
|
||||||
- SIEMPRE verificar working tree limpio
|
|
||||||
- SIEMPRE actualizar master antes de crear rama
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
---
|
|
||||||
name: git-push
|
|
||||||
description: Integra cambios a master y publica. Soporta ramas issue/* y quick/*.
|
|
||||||
disable-model-invocation: true
|
|
||||||
user-invocable: true
|
|
||||||
allowed-tools: Bash, Read, Write, Edit
|
|
||||||
---
|
|
||||||
|
|
||||||
# git-push
|
|
||||||
|
|
||||||
Integra cambios a master y publica al remoto. Detecta automáticamente la rama actual.
|
|
||||||
|
|
||||||
## Sintaxis
|
|
||||||
|
|
||||||
```bash
|
|
||||||
/git-push
|
|
||||||
```
|
|
||||||
|
|
||||||
## Flujo
|
|
||||||
|
|
||||||
### 1. Verificar rama actual y estado
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git branch --show-current
|
|
||||||
git status --short
|
|
||||||
```
|
|
||||||
|
|
||||||
**Caso A: En rama issue/* o quick/*** - Continuar al paso 2
|
|
||||||
|
|
||||||
**Caso B: En master con cambios** - Crear rama quick automáticamente:
|
|
||||||
- Analizar archivos modificados para generar slug
|
|
||||||
- `git checkout -b quick/<slug-generado>`
|
|
||||||
|
|
||||||
**Caso C: En master sin cambios** - STOP: "No hay nada que publicar"
|
|
||||||
|
|
||||||
### 2. Crear commits por bloque lógico
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git status --short
|
|
||||||
git diff --stat
|
|
||||||
```
|
|
||||||
|
|
||||||
Agrupar cambios por tipo y crear commits atómicos:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git add <archivos_bloque_1>
|
|
||||||
git commit -m "<tipo>: <resumen>" -m "<descripción en español>"
|
|
||||||
```
|
|
||||||
|
|
||||||
**Tipos:** feat, fix, refactor, docs, chore, test
|
|
||||||
|
|
||||||
**Reglas de commits:**
|
|
||||||
- No WIP
|
|
||||||
- No mezclar tipos
|
|
||||||
- Descripción larga obligatoria en español
|
|
||||||
|
|
||||||
### 3. Ejecutar tests
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go test -tags goolm ./...
|
|
||||||
```
|
|
||||||
|
|
||||||
- Tests pasan: continuar
|
|
||||||
- Tests fallan: STOP y corregir
|
|
||||||
- No hay tests: informar y continuar
|
|
||||||
|
|
||||||
### 4. Merge a master
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git checkout master
|
|
||||||
git pull --rebase
|
|
||||||
git merge --no-ff <rama> -m "merge: <rama> — <título>"
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5. Push a remoto
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git push
|
|
||||||
```
|
|
||||||
|
|
||||||
### 6. Limpiar rama local
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git branch -d <rama>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 7. Verificación final
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git log --oneline -3
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Rama `<rama>` integrada a master y publicada
|
|
||||||
|
|
||||||
Commits creados:
|
|
||||||
- <commit 1>
|
|
||||||
- merge: <rama>
|
|
||||||
|
|
||||||
Rama local eliminada.
|
|
||||||
```
|
|
||||||
|
|
||||||
## Convenciones
|
|
||||||
|
|
||||||
- Commits atómicos
|
|
||||||
- Tests obligatorios antes de merge
|
|
||||||
- Merge --no-ff siempre
|
|
||||||
- Push inmediato
|
|
||||||
|
|
||||||
## Reglas
|
|
||||||
|
|
||||||
- NO commits WIP
|
|
||||||
- NO mezclar tipos en un commit
|
|
||||||
- NO saltear tests
|
|
||||||
- NO push --force a master
|
|
||||||
- SIEMPRE usar --no-ff
|
|
||||||
@@ -1,105 +0,0 @@
|
|||||||
---
|
|
||||||
name: git-recovery
|
|
||||||
description: Recupera el repositorio de estados inconsistentes (worktrees huérfanos, branches bloqueados)
|
|
||||||
argument-hint: [--aggressive]
|
|
||||||
disable-model-invocation: true
|
|
||||||
user-invocable: true
|
|
||||||
allowed-tools: Bash, Read
|
|
||||||
---
|
|
||||||
|
|
||||||
# git-recovery
|
|
||||||
|
|
||||||
Recupera el repositorio de estados inconsistentes causados por worktrees huérfanos, branches bloqueados o conflictos git.
|
|
||||||
|
|
||||||
## Sintaxis
|
|
||||||
|
|
||||||
```bash
|
|
||||||
/git-recovery # Recuperación estándar
|
|
||||||
/git-recovery --aggressive # Limpieza agresiva
|
|
||||||
```
|
|
||||||
|
|
||||||
## Cuándo usar
|
|
||||||
|
|
||||||
- Errores "exit status 128" al crear worktrees
|
|
||||||
- Git reporta "worktree already exists"
|
|
||||||
- Branches que no se pueden eliminar
|
|
||||||
- Worktrees huérfanos en `git worktree list`
|
|
||||||
|
|
||||||
## Flujo
|
|
||||||
|
|
||||||
### 1. Diagnóstico inicial
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git branch --show-current
|
|
||||||
git status --porcelain
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Análisis de problemas
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git worktree list
|
|
||||||
git branch --list
|
|
||||||
git remote -v
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Limpieza de worktrees huérfanos
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git worktree prune -v
|
|
||||||
```
|
|
||||||
|
|
||||||
Si existe directorio `worktrees/`:
|
|
||||||
- Verificar cada worktree contra `git worktree list`
|
|
||||||
- Eliminar directorios huérfanos
|
|
||||||
|
|
||||||
### 4. Verificar branches bloqueados
|
|
||||||
|
|
||||||
Para cada branch issue/* o quick/*:
|
|
||||||
- Si está mergeada: `git branch -d <branch>`
|
|
||||||
- Si NO está mergeada: advertir
|
|
||||||
|
|
||||||
### 5. Sincronizar con remoto
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git checkout master
|
|
||||||
git fetch origin
|
|
||||||
git pull --rebase origin master
|
|
||||||
```
|
|
||||||
|
|
||||||
### 6. Modo agresivo (solo con --aggressive)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git remote prune origin -v
|
|
||||||
git fsck --full
|
|
||||||
git gc --prune=now
|
|
||||||
rm -f .git/index.lock # si existe
|
|
||||||
```
|
|
||||||
|
|
||||||
### 7. Verificación final
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git status
|
|
||||||
git worktree list
|
|
||||||
git branch --list
|
|
||||||
```
|
|
||||||
|
|
||||||
## Patrones de error que activan recovery
|
|
||||||
|
|
||||||
- `exit status 128`
|
|
||||||
- `worktree .* already exists`
|
|
||||||
- `reference is not a tree`
|
|
||||||
- `cannot lock ref`
|
|
||||||
- `index.lock`
|
|
||||||
|
|
||||||
## Convenciones
|
|
||||||
|
|
||||||
- No destructivo por defecto
|
|
||||||
- Modo agresivo solo con flag explícito
|
|
||||||
- Siempre sincroniza con remoto
|
|
||||||
- Preserva cambios locales
|
|
||||||
|
|
||||||
## Reglas
|
|
||||||
|
|
||||||
- NUNCA git reset --hard sin --aggressive
|
|
||||||
- NUNCA eliminar branches no mergeadas automáticamente
|
|
||||||
- SIEMPRE sincronizar con remoto después de limpieza
|
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
---
|
|
||||||
name: import-repo
|
|
||||||
description: Importa repositorios existentes al sistema Dataforge desde URL remota o local
|
|
||||||
disable-model-invocation: true
|
|
||||||
user-invocable: true
|
|
||||||
allowed-tools: Bash, Read, Write
|
|
||||||
---
|
|
||||||
|
|
||||||
# import-repo
|
|
||||||
|
|
||||||
Importa repositorios existentes: desde GitHub/GitLab/Gitea, o adoptando un repo local.
|
|
||||||
|
|
||||||
## Prerequisitos
|
|
||||||
|
|
||||||
- Variables: `GITEA_URL` y `GITEA_TOKEN`
|
|
||||||
- Feature flag `workspace_commands` habilitado
|
|
||||||
|
|
||||||
## Modos
|
|
||||||
|
|
||||||
### Desde URL remota
|
|
||||||
|
|
||||||
1. Crear repo vacío en Gitea
|
|
||||||
2. Clonar origen con `git clone --mirror`
|
|
||||||
3. Push a Gitea con `git push --mirror`
|
|
||||||
4. Clonar en `workspaces/`
|
|
||||||
5. Registrar en BD
|
|
||||||
|
|
||||||
### Adoptar repo local
|
|
||||||
|
|
||||||
1. Verificar que existe `.git`
|
|
||||||
2. Crear repo vacío en Gitea
|
|
||||||
3. Añadir remote `gitea`
|
|
||||||
4. Push de branches y tags
|
|
||||||
5. Registrar en BD
|
|
||||||
|
|
||||||
## Flujo interactivo
|
|
||||||
|
|
||||||
### 1. Solicitar fuente
|
|
||||||
|
|
||||||
```
|
|
||||||
Fuente del repositorio:
|
|
||||||
- URL remota (ej: https://github.com/user/repo)
|
|
||||||
- Nombre local en workspaces/ (ej: legacy-tool)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Detectar modo y analizar
|
|
||||||
|
|
||||||
Usa `core.DetectImportMode(source)`
|
|
||||||
|
|
||||||
### 3. Solicitar nombre de destino
|
|
||||||
|
|
||||||
```
|
|
||||||
Nombre en Gitea (Enter para usar 'nombre-sugerido'):
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. Verificar que no existe en Gitea
|
|
||||||
|
|
||||||
### 5. Opciones adicionales
|
|
||||||
|
|
||||||
```
|
|
||||||
¿Repositorio privado? (s/N):
|
|
||||||
Descripción (opcional):
|
|
||||||
```
|
|
||||||
|
|
||||||
### 6. Resumen y confirmación
|
|
||||||
|
|
||||||
```
|
|
||||||
Resumen:
|
|
||||||
Fuente: https://...
|
|
||||||
Destino: gitea.example.com/...
|
|
||||||
Tipo: importar desde URL remota
|
|
||||||
|
|
||||||
¿Importar? (s/N):
|
|
||||||
```
|
|
||||||
|
|
||||||
### 7. Ejecutar importación
|
|
||||||
|
|
||||||
### 8. Mostrar resultado
|
|
||||||
|
|
||||||
```
|
|
||||||
Repositorio importado exitosamente.
|
|
||||||
|
|
||||||
Workspace: workspaces/nombre
|
|
||||||
Gitea URL: https://...
|
|
||||||
```
|
|
||||||
|
|
||||||
## Convenciones
|
|
||||||
|
|
||||||
- Confirmación obligatoria
|
|
||||||
- Rollback automático si falla
|
|
||||||
- Historia Git siempre preservada
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
---
|
|
||||||
name: init-frontend
|
|
||||||
description: Inicializa proyecto frontend (React/Vite) o desktop (Wails) con Frontend_Library
|
|
||||||
disable-model-invocation: true
|
|
||||||
user-invocable: true
|
|
||||||
allowed-tools: Bash, Read, Write, Edit
|
|
||||||
---
|
|
||||||
|
|
||||||
# init-frontend
|
|
||||||
|
|
||||||
Inicializa un proyecto frontend (webapp React/Vite) o desktop (Wails + Go + React). Coherente con Frontend_Library y el stack del frontend-lib/build-wails agents.
|
|
||||||
|
|
||||||
## Sintaxis
|
|
||||||
|
|
||||||
```bash
|
|
||||||
/init-frontend [nombre] [--wails] [--path /ruta/destino]
|
|
||||||
```
|
|
||||||
|
|
||||||
- `nombre`: nombre del proyecto (kebab-case). Si no se da, se pregunta.
|
|
||||||
- `--wails`: modo desktop con Wails (Go backend + React frontend). Sin flag = webapp pura.
|
|
||||||
- `--path`: directorio destino. Default: directorio actual.
|
|
||||||
|
|
||||||
## Flujo
|
|
||||||
|
|
||||||
### 1. Ejecutar script de setup
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bash "${CLAUDE_SKILL_DIR}/setup-frontend.sh" [nombre] [--wails] [path]
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Si el script reporta STATUS: CONFIGURED
|
|
||||||
|
|
||||||
Informar al usuario que el proyecto ya existe.
|
|
||||||
|
|
||||||
### 3. Si el script reporta STATUS: READY
|
|
||||||
|
|
||||||
Mostrar resumen según modo:
|
|
||||||
|
|
||||||
**Webapp:**
|
|
||||||
- `pnpm dev` para desarrollo
|
|
||||||
- `pnpm build` para producción
|
|
||||||
- Frontend_Library linkeada via pnpm
|
|
||||||
|
|
||||||
**Wails:**
|
|
||||||
- `make dev` para desarrollo con hot reload
|
|
||||||
- `make build` para compilar
|
|
||||||
- Frontend_Library + DevFactory integrados
|
|
||||||
- Bindings Go→TS auto-generados
|
|
||||||
|
|
||||||
### 4. Si el script reporta STATUS: ERROR
|
|
||||||
|
|
||||||
Mostrar el error y sugerir corrección.
|
|
||||||
|
|
||||||
## Convenciones
|
|
||||||
|
|
||||||
- pnpm exclusivamente (no npm ni yarn)
|
|
||||||
- React 19 + TypeScript + Vite + Tailwind CSS 4
|
|
||||||
- @anthropic/frontend-lib via pnpm link
|
|
||||||
- Temas OKLCH con semantic tokens
|
|
||||||
- Phosphor Icons
|
|
||||||
- Vite dedupe obligatorio para react/react-dom
|
|
||||||
- En modo Wails: go.work con DevFactory, patrón pure core / impure shell
|
|
||||||
@@ -1,438 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
# =============================================================================
|
|
||||||
# setup-frontend.sh — Inicializa proyecto React/Vite o Wails desktop
|
|
||||||
# Coherente con Frontend_Library + DevFactory + build-wails agent
|
|
||||||
# =============================================================================
|
|
||||||
|
|
||||||
# --- Colores ---
|
|
||||||
RED='\033[0;31m'
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
BLUE='\033[0;34m'
|
|
||||||
CYAN='\033[0;36m'
|
|
||||||
NC='\033[0m'
|
|
||||||
|
|
||||||
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
|
||||||
log_ok() { echo -e "${GREEN}[OK]${NC} $1"; }
|
|
||||||
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
|
||||||
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
|
||||||
log_step() { echo -e "${CYAN}[STEP]${NC} $1"; }
|
|
||||||
|
|
||||||
# --- Parámetros ---
|
|
||||||
PROJECT_NAME=""
|
|
||||||
WAILS_MODE=false
|
|
||||||
TARGET_PATH="."
|
|
||||||
|
|
||||||
while [[ $# -gt 0 ]]; do
|
|
||||||
case "$1" in
|
|
||||||
--wails) WAILS_MODE=true; shift ;;
|
|
||||||
--path) TARGET_PATH="$2"; shift 2 ;;
|
|
||||||
-*) log_error "Flag desconocido: $1"; echo "STATUS: ERROR"; exit 1 ;;
|
|
||||||
*) PROJECT_NAME="$1"; shift ;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
# --- Rutas de librerías ---
|
|
||||||
FRONTEND_LIB="$HOME/.local_agentes/frontend/frontend"
|
|
||||||
DEVFACTORY_PATH="$HOME/.local_agentes/backend"
|
|
||||||
TEMPLATES_DIR="$HOME/.local_agentes/frontend/templates/base"
|
|
||||||
WAILS_TEMPLATES="$HOME/.claude/agents/build-wails/templates"
|
|
||||||
|
|
||||||
# --- Validar nombre ---
|
|
||||||
if [[ -z "$PROJECT_NAME" ]]; then
|
|
||||||
log_error "Uso: setup-frontend.sh <nombre> [--wails] [--path /ruta]"
|
|
||||||
echo "STATUS: ERROR"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Normalizar
|
|
||||||
PROJECT_NAME=$(echo "$PROJECT_NAME" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]/-/g' | sed 's/--*/-/g' | sed 's/^-\|-$//g')
|
|
||||||
PROJECT_DIR="$TARGET_PATH/$PROJECT_NAME"
|
|
||||||
|
|
||||||
# --- Check estado existente ---
|
|
||||||
if [[ -f "$PROJECT_DIR/package.json" ]] || [[ -f "$PROJECT_DIR/wails.json" ]]; then
|
|
||||||
log_warn "El proyecto $PROJECT_NAME ya existe en $PROJECT_DIR"
|
|
||||||
echo "STATUS: CONFIGURED"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# --- Verificar dependencias ---
|
|
||||||
log_step "Verificando dependencias..."
|
|
||||||
|
|
||||||
if ! command -v pnpm &>/dev/null; then
|
|
||||||
log_error "pnpm no está instalado. Instala con: npm install -g pnpm"
|
|
||||||
echo "STATUS: ERROR"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
log_ok "pnpm $(pnpm --version) encontrado"
|
|
||||||
|
|
||||||
if ! command -v node &>/dev/null; then
|
|
||||||
log_error "Node.js no encontrado"
|
|
||||||
echo "STATUS: ERROR"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
log_ok "Node $(node --version) encontrado"
|
|
||||||
|
|
||||||
if [[ "$WAILS_MODE" == true ]]; then
|
|
||||||
if ! command -v wails &>/dev/null; then
|
|
||||||
log_error "Wails no está instalado. Instala con: go install github.com/wailsapp/wails/v2/cmd/wails@latest"
|
|
||||||
echo "STATUS: ERROR"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
log_ok "Wails $(wails version 2>/dev/null | head -1 || echo 'v2.x') encontrado"
|
|
||||||
|
|
||||||
if ! command -v go &>/dev/null; then
|
|
||||||
log_error "Go no encontrado (requerido para Wails)"
|
|
||||||
echo "STATUS: ERROR"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
log_ok "Go $(go version | grep -oP '\d+\.\d+' | head -1) encontrado"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ! -d "$FRONTEND_LIB" ]]; then
|
|
||||||
log_warn "Frontend_Library no encontrada en $FRONTEND_LIB — se creará sin link"
|
|
||||||
HAS_FRONTEND_LIB=false
|
|
||||||
else
|
|
||||||
log_ok "Frontend_Library encontrada"
|
|
||||||
HAS_FRONTEND_LIB=true
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ============================================================================
|
|
||||||
# MODO WAILS — Desktop app (Go + React)
|
|
||||||
# ============================================================================
|
|
||||||
if [[ "$WAILS_MODE" == true ]]; then
|
|
||||||
log_step "Creando proyecto Wails '$PROJECT_NAME'..."
|
|
||||||
|
|
||||||
# Usar wails init con template react-ts
|
|
||||||
wails init -n "$PROJECT_NAME" -t react-ts -d "$TARGET_PATH" 2>/dev/null
|
|
||||||
|
|
||||||
cd "$PROJECT_DIR"
|
|
||||||
|
|
||||||
# --- go.work con DevFactory ---
|
|
||||||
if [[ -d "$DEVFACTORY_PATH" ]]; then
|
|
||||||
log_step "Configurando go.work con DevFactory..."
|
|
||||||
cat > go.work << EOF
|
|
||||||
go 1.22
|
|
||||||
|
|
||||||
use (
|
|
||||||
.
|
|
||||||
$DEVFACTORY_PATH
|
|
||||||
)
|
|
||||||
EOF
|
|
||||||
log_ok "DevFactory enlazado via go.work"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# --- Configurar frontend con pnpm ---
|
|
||||||
log_step "Configurando frontend con pnpm..."
|
|
||||||
cd frontend
|
|
||||||
|
|
||||||
# Reemplazar npm por pnpm en wails.json
|
|
||||||
cd ..
|
|
||||||
if [[ -f "wails.json" ]]; then
|
|
||||||
sed -i 's/"npm install"/"pnpm install"/g' wails.json
|
|
||||||
sed -i 's/"npm run dev"/"pnpm dev"/g' wails.json
|
|
||||||
sed -i 's/"npm run build"/"pnpm build"/g' wails.json
|
|
||||||
fi
|
|
||||||
cd frontend
|
|
||||||
|
|
||||||
# Instalar con pnpm
|
|
||||||
rm -f package-lock.json 2>/dev/null || true
|
|
||||||
pnpm install
|
|
||||||
|
|
||||||
# --- Linkear Frontend_Library ---
|
|
||||||
if [[ "$HAS_FRONTEND_LIB" == true ]]; then
|
|
||||||
log_step "Linkeando Frontend_Library..."
|
|
||||||
pnpm add "@anthropic/frontend-lib@link:$FRONTEND_LIB"
|
|
||||||
log_ok "@anthropic/frontend-lib linkeada"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# --- Instalar Tailwind CSS 4 ---
|
|
||||||
log_step "Instalando Tailwind CSS 4..."
|
|
||||||
pnpm add -D tailwindcss @tailwindcss/vite
|
|
||||||
|
|
||||||
# --- Configurar vite.config.ts con dedupe y tailwind ---
|
|
||||||
log_step "Configurando Vite (dedupe + tailwind)..."
|
|
||||||
cat > vite.config.ts << 'VEOF'
|
|
||||||
import { defineConfig } from 'vite'
|
|
||||||
import react from '@vitejs/plugin-react'
|
|
||||||
import tailwindcss from '@tailwindcss/vite'
|
|
||||||
import { resolve } from 'path'
|
|
||||||
|
|
||||||
export default defineConfig({
|
|
||||||
plugins: [react(), tailwindcss()],
|
|
||||||
resolve: {
|
|
||||||
alias: {
|
|
||||||
'@': resolve(__dirname, './src'),
|
|
||||||
'@wails': resolve(__dirname, './wailsjs'),
|
|
||||||
},
|
|
||||||
dedupe: ['react', 'react-dom'],
|
|
||||||
},
|
|
||||||
})
|
|
||||||
VEOF
|
|
||||||
|
|
||||||
# --- CSS base con Tailwind ---
|
|
||||||
cat > src/style.css << 'CSSEOF'
|
|
||||||
@import "tailwindcss";
|
|
||||||
CSSEOF
|
|
||||||
|
|
||||||
# --- Instalar Phosphor Icons ---
|
|
||||||
pnpm add @phosphor-icons/react
|
|
||||||
|
|
||||||
cd ..
|
|
||||||
|
|
||||||
# --- Makefile (basado en build-wails agent) ---
|
|
||||||
log_step "Generando Makefile..."
|
|
||||||
cat > Makefile << 'MKEOF'
|
|
||||||
.PHONY: dev dev-debug build build-prod build-linux build-windows build-all clean generate doctor
|
|
||||||
|
|
||||||
APP_NAME := $(shell basename $(CURDIR))
|
|
||||||
|
|
||||||
## dev: Desarrollo con hot reload
|
|
||||||
dev:
|
|
||||||
wails dev
|
|
||||||
|
|
||||||
## dev-debug: Desarrollo con DevTools
|
|
||||||
dev-debug:
|
|
||||||
wails dev -devtools
|
|
||||||
|
|
||||||
## build: Build para plataforma actual
|
|
||||||
build:
|
|
||||||
wails build
|
|
||||||
|
|
||||||
## build-prod: Build optimizado para producción
|
|
||||||
build-prod:
|
|
||||||
wails build -clean -trimpath -ldflags="-s -w"
|
|
||||||
|
|
||||||
## build-linux: Build para Linux AMD64
|
|
||||||
build-linux:
|
|
||||||
wails build -platform linux/amd64
|
|
||||||
|
|
||||||
## build-windows: Cross-compile para Windows
|
|
||||||
build-windows:
|
|
||||||
wails build -platform windows/amd64
|
|
||||||
|
|
||||||
## build-all: Linux + Windows
|
|
||||||
build-all: build-linux build-windows
|
|
||||||
|
|
||||||
## generate: Regenerar bindings TypeScript
|
|
||||||
generate:
|
|
||||||
wails generate module
|
|
||||||
|
|
||||||
## clean: Limpiar artefactos
|
|
||||||
clean:
|
|
||||||
rm -rf build/bin frontend/dist
|
|
||||||
|
|
||||||
## doctor: Verificar instalación
|
|
||||||
doctor:
|
|
||||||
wails doctor
|
|
||||||
|
|
||||||
## help: Muestra esta ayuda
|
|
||||||
help:
|
|
||||||
@grep -E '^## ' Makefile | sed 's/## //' | column -t -s ':'
|
|
||||||
MKEOF
|
|
||||||
|
|
||||||
# --- .gitignore ---
|
|
||||||
cat >> .gitignore << 'EOF'
|
|
||||||
node_modules/
|
|
||||||
frontend/dist/
|
|
||||||
build/bin/
|
|
||||||
*.exe
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# --- Resumen Wails ---
|
|
||||||
echo ""
|
|
||||||
log_ok "Proyecto Wails '$PROJECT_NAME' creado en $PROJECT_DIR"
|
|
||||||
echo ""
|
|
||||||
echo -e "${CYAN}Estructura:${NC}"
|
|
||||||
echo " $PROJECT_NAME/"
|
|
||||||
echo " ├── main.go, app.go — Backend Go"
|
|
||||||
echo " ├── go.work — Enlace a DevFactory"
|
|
||||||
echo " ├── frontend/ — React + TypeScript + Vite"
|
|
||||||
echo " │ ├── src/ — Componentes React"
|
|
||||||
echo " │ └── wailsjs/ — Bindings auto-generados"
|
|
||||||
echo " ├── Makefile — dev, build, build-all"
|
|
||||||
echo " └── wails.json — Configuración Wails"
|
|
||||||
echo ""
|
|
||||||
echo -e "${CYAN}Comandos:${NC}"
|
|
||||||
echo " make dev — Desarrollo con hot reload"
|
|
||||||
echo " make build — Compilar app desktop"
|
|
||||||
echo " make build-all — Linux + Windows"
|
|
||||||
echo " make generate — Regenerar bindings TS"
|
|
||||||
echo ""
|
|
||||||
if [[ "$HAS_FRONTEND_LIB" == true ]]; then
|
|
||||||
echo -e "${CYAN}Frontend_Library:${NC}"
|
|
||||||
echo " import { Button, Card } from '@anthropic/frontend-lib'"
|
|
||||||
echo " import { useTheme } from '@anthropic/frontend-lib/hooks'"
|
|
||||||
echo ""
|
|
||||||
fi
|
|
||||||
echo "STATUS: READY"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ============================================================================
|
|
||||||
# MODO WEBAPP — React + Vite (sin Wails)
|
|
||||||
# ============================================================================
|
|
||||||
log_step "Creando proyecto webapp '$PROJECT_NAME'..."
|
|
||||||
|
|
||||||
mkdir -p "$PROJECT_DIR"
|
|
||||||
cd "$PROJECT_DIR"
|
|
||||||
|
|
||||||
# --- Usar template de Frontend_Library si existe ---
|
|
||||||
if [[ -d "$TEMPLATES_DIR" ]]; then
|
|
||||||
log_step "Usando template de Frontend_Library..."
|
|
||||||
cp -r "$TEMPLATES_DIR"/* .
|
|
||||||
cp -r "$TEMPLATES_DIR"/.[!.]* . 2>/dev/null || true
|
|
||||||
else
|
|
||||||
log_step "Creando desde cero con Vite..."
|
|
||||||
|
|
||||||
# package.json
|
|
||||||
cat > package.json << PKGEOF
|
|
||||||
{
|
|
||||||
"name": "$PROJECT_NAME",
|
|
||||||
"private": true,
|
|
||||||
"version": "0.1.0",
|
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
|
||||||
"dev": "vite",
|
|
||||||
"build": "tsc -b && vite build",
|
|
||||||
"preview": "vite preview"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PKGEOF
|
|
||||||
|
|
||||||
# Instalar dependencias base
|
|
||||||
pnpm add react react-dom
|
|
||||||
pnpm add -D typescript @types/react @types/react-dom
|
|
||||||
pnpm add -D vite @vitejs/plugin-react
|
|
||||||
pnpm add -D tailwindcss @tailwindcss/vite
|
|
||||||
|
|
||||||
# tsconfig.json
|
|
||||||
cat > tsconfig.json << 'TSEOF'
|
|
||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"target": "ES2023",
|
|
||||||
"lib": ["ES2023", "DOM", "DOM.Iterable"],
|
|
||||||
"module": "ESNext",
|
|
||||||
"moduleResolution": "bundler",
|
|
||||||
"jsx": "react-jsx",
|
|
||||||
"strict": true,
|
|
||||||
"noUnusedLocals": true,
|
|
||||||
"noUnusedParameters": true,
|
|
||||||
"paths": { "@/*": ["./src/*"] },
|
|
||||||
"skipLibCheck": true
|
|
||||||
},
|
|
||||||
"include": ["src"]
|
|
||||||
}
|
|
||||||
TSEOF
|
|
||||||
|
|
||||||
# vite.config.ts
|
|
||||||
cat > vite.config.ts << 'VEOF'
|
|
||||||
import { defineConfig } from 'vite'
|
|
||||||
import react from '@vitejs/plugin-react'
|
|
||||||
import tailwindcss from '@tailwindcss/vite'
|
|
||||||
import { resolve } from 'path'
|
|
||||||
|
|
||||||
export default defineConfig({
|
|
||||||
plugins: [react(), tailwindcss()],
|
|
||||||
resolve: {
|
|
||||||
alias: { '@': resolve(__dirname, './src') },
|
|
||||||
dedupe: ['react', 'react-dom'],
|
|
||||||
},
|
|
||||||
})
|
|
||||||
VEOF
|
|
||||||
|
|
||||||
# index.html
|
|
||||||
cat > index.html << HTMLEOF
|
|
||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<title>$PROJECT_NAME</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="root"></div>
|
|
||||||
<script type="module" src="/src/main.tsx"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
HTMLEOF
|
|
||||||
|
|
||||||
# src/
|
|
||||||
mkdir -p src
|
|
||||||
|
|
||||||
cat > src/main.tsx << 'TSXEOF'
|
|
||||||
import { StrictMode } from 'react'
|
|
||||||
import { createRoot } from 'react-dom/client'
|
|
||||||
import App from './App'
|
|
||||||
import './app.css'
|
|
||||||
|
|
||||||
createRoot(document.getElementById('root')!).render(
|
|
||||||
<StrictMode>
|
|
||||||
<App />
|
|
||||||
</StrictMode>,
|
|
||||||
)
|
|
||||||
TSXEOF
|
|
||||||
|
|
||||||
cat > src/App.tsx << 'TSXEOF'
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<div className="min-h-screen bg-surface text-foreground flex items-center justify-center">
|
|
||||||
<h1 className="text-3xl font-bold">Ready</h1>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default App
|
|
||||||
TSXEOF
|
|
||||||
|
|
||||||
cat > src/app.css << 'CSSEOF'
|
|
||||||
@import "tailwindcss";
|
|
||||||
CSSEOF
|
|
||||||
fi
|
|
||||||
|
|
||||||
# --- Linkear Frontend_Library ---
|
|
||||||
if [[ "$HAS_FRONTEND_LIB" == true ]]; then
|
|
||||||
log_step "Linkeando Frontend_Library..."
|
|
||||||
pnpm add "@anthropic/frontend-lib@link:$FRONTEND_LIB"
|
|
||||||
log_ok "@anthropic/frontend-lib linkeada"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# --- Phosphor Icons ---
|
|
||||||
pnpm add @phosphor-icons/react
|
|
||||||
|
|
||||||
# --- .gitignore ---
|
|
||||||
cat > .gitignore << 'EOF'
|
|
||||||
node_modules/
|
|
||||||
dist/
|
|
||||||
.vite/
|
|
||||||
*.local
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# --- Resumen Webapp ---
|
|
||||||
echo ""
|
|
||||||
log_ok "Proyecto webapp '$PROJECT_NAME' creado en $PROJECT_DIR"
|
|
||||||
echo ""
|
|
||||||
echo -e "${CYAN}Estructura:${NC}"
|
|
||||||
echo " $PROJECT_NAME/"
|
|
||||||
echo " ├── src/"
|
|
||||||
echo " │ ├── App.tsx — Componente principal"
|
|
||||||
echo " │ ├── main.tsx — Entry point"
|
|
||||||
echo " │ └── app.css — Tailwind CSS"
|
|
||||||
echo " ├── vite.config.ts — Vite + Tailwind + dedupe"
|
|
||||||
echo " ├── tsconfig.json — TypeScript strict"
|
|
||||||
echo " └── package.json — pnpm"
|
|
||||||
echo ""
|
|
||||||
echo -e "${CYAN}Comandos:${NC}"
|
|
||||||
echo " pnpm dev — Servidor de desarrollo"
|
|
||||||
echo " pnpm build — Build de producción"
|
|
||||||
echo " pnpm preview — Preview del build"
|
|
||||||
echo ""
|
|
||||||
if [[ "$HAS_FRONTEND_LIB" == true ]]; then
|
|
||||||
echo -e "${CYAN}Frontend_Library:${NC}"
|
|
||||||
echo " import { Button, Card } from '@anthropic/frontend-lib'"
|
|
||||||
echo " import { useTheme } from '@anthropic/frontend-lib/hooks'"
|
|
||||||
echo ""
|
|
||||||
fi
|
|
||||||
echo "STATUS: READY"
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
---
|
|
||||||
name: init-go-module
|
|
||||||
description: Inicializa un módulo Go funcional con bindings Python (CGO c-shared + ctypes)
|
|
||||||
disable-model-invocation: true
|
|
||||||
user-invocable: true
|
|
||||||
allowed-tools: Bash, Read, Write, Edit
|
|
||||||
---
|
|
||||||
|
|
||||||
# init-go-module
|
|
||||||
|
|
||||||
Inicializa un módulo Go con arquitectura funcional (pure core / impure shell) y bindings Python automáticos via CGO c-shared + ctypes. Coherente con DevFactory y el stack del backend-lib agent.
|
|
||||||
|
|
||||||
## Sintaxis
|
|
||||||
|
|
||||||
```bash
|
|
||||||
/init-go-module [nombre] [--path /ruta/destino]
|
|
||||||
```
|
|
||||||
|
|
||||||
- `nombre`: nombre del módulo (kebab-case). Si no se da, se pregunta.
|
|
||||||
- `--path`: directorio destino. Default: directorio actual.
|
|
||||||
|
|
||||||
## Flujo
|
|
||||||
|
|
||||||
### 1. Ejecutar script de setup
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bash "${CLAUDE_SKILL_DIR}/setup-go-module.sh" [nombre] [path]
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Si el script reporta STATUS: CONFIGURED
|
|
||||||
|
|
||||||
Informar al usuario que el módulo ya está configurado.
|
|
||||||
|
|
||||||
### 3. Si el script reporta STATUS: READY
|
|
||||||
|
|
||||||
Mostrar resumen:
|
|
||||||
- Estructura creada
|
|
||||||
- Cómo compilar: `make build`
|
|
||||||
- Cómo generar bindings Python: `make python`
|
|
||||||
- Cómo testear: `make test`
|
|
||||||
- Cómo usar desde Python: `from bindings.modulo import *`
|
|
||||||
|
|
||||||
### 4. Si el script reporta STATUS: ERROR
|
|
||||||
|
|
||||||
Mostrar el error y sugerir corrección.
|
|
||||||
|
|
||||||
## Convenciones
|
|
||||||
|
|
||||||
- Usa DevFactory como dependencia via `go.work` (igual que build-wails)
|
|
||||||
- Patrón pure core / impure shell de DevFactory
|
|
||||||
- `Result[T]` y `Option[T]` del core de DevFactory
|
|
||||||
- Funciones exportadas a Python son thin wrappers en `export/`
|
|
||||||
- El wrapper Python se auto-genera desde los `//export` comments
|
|
||||||
@@ -1,466 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
# =============================================================================
|
|
||||||
# setup-go-module.sh — Inicializa módulo Go funcional con bindings Python
|
|
||||||
# Coherente con DevFactory (pure core / impure shell) + CGO c-shared + ctypes
|
|
||||||
# =============================================================================
|
|
||||||
|
|
||||||
# --- Colores ---
|
|
||||||
RED='\033[0;31m'
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
BLUE='\033[0;34m'
|
|
||||||
CYAN='\033[0;36m'
|
|
||||||
NC='\033[0m'
|
|
||||||
|
|
||||||
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
|
||||||
log_ok() { echo -e "${GREEN}[OK]${NC} $1"; }
|
|
||||||
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
|
||||||
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
|
||||||
log_step() { echo -e "${CYAN}[STEP]${NC} $1"; }
|
|
||||||
|
|
||||||
# --- Parámetros ---
|
|
||||||
MODULE_NAME="${1:-}"
|
|
||||||
TARGET_PATH="${2:-.}"
|
|
||||||
DEVFACTORY_PATH="$HOME/.local_agentes/backend"
|
|
||||||
DEVFACTORY_MODULE="github.com/lucasdataproyects/devfactory"
|
|
||||||
|
|
||||||
# --- Validar nombre ---
|
|
||||||
if [[ -z "$MODULE_NAME" ]]; then
|
|
||||||
log_error "Uso: setup-go-module.sh <nombre> [path]"
|
|
||||||
echo "STATUS: ERROR"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Normalizar nombre a kebab-case
|
|
||||||
MODULE_NAME=$(echo "$MODULE_NAME" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]/-/g' | sed 's/--*/-/g' | sed 's/^-\|-$//g')
|
|
||||||
PROJECT_DIR="$TARGET_PATH/$MODULE_NAME"
|
|
||||||
|
|
||||||
# --- Check estado existente ---
|
|
||||||
if [[ -f "$PROJECT_DIR/go.mod" ]]; then
|
|
||||||
log_warn "El módulo $MODULE_NAME ya existe en $PROJECT_DIR"
|
|
||||||
if [[ -f "$PROJECT_DIR/export/exports.go" ]]; then
|
|
||||||
log_ok "Bindings Python ya configurados"
|
|
||||||
else
|
|
||||||
log_warn "Falta directorio export/ — ejecuta de nuevo para completar"
|
|
||||||
fi
|
|
||||||
echo "STATUS: CONFIGURED"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# --- Verificar dependencias ---
|
|
||||||
log_step "Verificando dependencias..."
|
|
||||||
|
|
||||||
if ! command -v go &>/dev/null; then
|
|
||||||
log_error "Go no está instalado. Instala Go 1.22+"
|
|
||||||
echo "STATUS: ERROR"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
GO_VERSION=$(go version | grep -oP '\d+\.\d+' | head -1)
|
|
||||||
log_ok "Go $GO_VERSION encontrado"
|
|
||||||
|
|
||||||
if ! command -v python3 &>/dev/null; then
|
|
||||||
log_warn "Python3 no encontrado — los bindings se generarán pero no se podrán testear"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ! -d "$DEVFACTORY_PATH" ]]; then
|
|
||||||
log_warn "DevFactory no encontrado en $DEVFACTORY_PATH — se creará go.mod sin go.work"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# --- Crear estructura ---
|
|
||||||
log_step "Creando estructura del módulo '$MODULE_NAME'..."
|
|
||||||
|
|
||||||
mkdir -p "$PROJECT_DIR"/{core,shell,export,python/bindings,cmd,internal}
|
|
||||||
|
|
||||||
# --- go.mod ---
|
|
||||||
log_step "Generando go.mod..."
|
|
||||||
cat > "$PROJECT_DIR/go.mod" << EOF
|
|
||||||
module github.com/lucasdataproyects/$MODULE_NAME
|
|
||||||
|
|
||||||
go 1.22
|
|
||||||
|
|
||||||
require $DEVFACTORY_MODULE v0.0.0
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# --- go.work (si DevFactory existe localmente) ---
|
|
||||||
if [[ -d "$DEVFACTORY_PATH" ]]; then
|
|
||||||
log_step "Generando go.work con DevFactory local..."
|
|
||||||
cat > "$PROJECT_DIR/go.work" << EOF
|
|
||||||
go 1.22
|
|
||||||
|
|
||||||
use (
|
|
||||||
.
|
|
||||||
$DEVFACTORY_PATH
|
|
||||||
)
|
|
||||||
EOF
|
|
||||||
log_ok "go.work enlazado a DevFactory"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# --- core/transform.go — Funciones puras de ejemplo ---
|
|
||||||
log_step "Generando core/ (funciones puras)..."
|
|
||||||
cat > "$PROJECT_DIR/core/transform.go" << 'GOEOF'
|
|
||||||
// Package core contiene funciones puras sin side effects.
|
|
||||||
// Todas las funciones son deterministas y composables.
|
|
||||||
package core
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
df "github.com/lucasdataproyects/devfactory/core"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ToUpper transforma texto a mayúsculas (función pura).
|
|
||||||
func ToUpper(s string) string {
|
|
||||||
return strings.ToUpper(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProcessItems aplica una transformación a cada elemento usando MapSlice de DevFactory.
|
|
||||||
func ProcessItems(items []string, transform func(string) string) []string {
|
|
||||||
return df.MapSlice(items, transform)
|
|
||||||
}
|
|
||||||
|
|
||||||
// FilterNonEmpty filtra elementos vacíos usando FilterSlice de DevFactory.
|
|
||||||
func FilterNonEmpty(items []string) []string {
|
|
||||||
return df.FilterSlice(items, func(s string) bool {
|
|
||||||
return len(strings.TrimSpace(s)) > 0
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// SafeDivide retorna Result[float64] para evitar panic en división por cero.
|
|
||||||
func SafeDivide(a, b float64) df.Result[float64] {
|
|
||||||
if b == 0 {
|
|
||||||
return df.Err[float64](errors.New("division by zero"))
|
|
||||||
}
|
|
||||||
return df.Ok(a / b)
|
|
||||||
}
|
|
||||||
GOEOF
|
|
||||||
|
|
||||||
# --- core/types.go — Tipos exportables a Python ---
|
|
||||||
cat > "$PROJECT_DIR/core/types.go" << 'GOEOF'
|
|
||||||
package core
|
|
||||||
|
|
||||||
// DataPoint representa un punto de datos exportable a Python.
|
|
||||||
// Los campos usan tipos C-compatible para facilitar el binding.
|
|
||||||
type DataPoint struct {
|
|
||||||
Label string
|
|
||||||
Value float64
|
|
||||||
}
|
|
||||||
|
|
||||||
// Summary es el resultado de un procesamiento, exportable a Python.
|
|
||||||
type Summary struct {
|
|
||||||
Count int
|
|
||||||
Total float64
|
|
||||||
Items []string
|
|
||||||
}
|
|
||||||
GOEOF
|
|
||||||
|
|
||||||
# --- shell/io.go — Operaciones I/O con Result[T] ---
|
|
||||||
log_step "Generando shell/ (operaciones I/O)..."
|
|
||||||
cat > "$PROJECT_DIR/shell/io.go" << 'GOEOF'
|
|
||||||
// Package shell contiene operaciones con side effects, wrapeadas en Result[T].
|
|
||||||
package shell
|
|
||||||
|
|
||||||
import (
|
|
||||||
df "github.com/lucasdataproyects/devfactory/core"
|
|
||||||
"github.com/lucasdataproyects/devfactory/shell"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ReadDataFile lee un archivo y retorna su contenido como Result.
|
|
||||||
func ReadDataFile(path string) df.Result[string] {
|
|
||||||
return shell.ReadString(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WriteResult escribe un resultado a archivo.
|
|
||||||
func WriteResult(path string, content string) df.Result[struct{}] {
|
|
||||||
return shell.WriteString(path, content)
|
|
||||||
}
|
|
||||||
GOEOF
|
|
||||||
|
|
||||||
# --- export/exports.go — Funciones exportadas via CGO ---
|
|
||||||
log_step "Generando export/ (bindings CGO)..."
|
|
||||||
cat > "$PROJECT_DIR/export/exports.go" << GOEOF
|
|
||||||
// Package main exporta funciones Go como C shared library.
|
|
||||||
// Cada función con //export se expone como símbolo C callable desde Python.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import "C"
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"github.com/lucasdataproyects/$MODULE_NAME/core"
|
|
||||||
)
|
|
||||||
|
|
||||||
//export GoToUpper
|
|
||||||
func GoToUpper(input *C.char) *C.char {
|
|
||||||
result := core.ToUpper(C.GoString(input))
|
|
||||||
return C.CString(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
//export GoProcessItems
|
|
||||||
func GoProcessItems(jsonInput *C.char) *C.char {
|
|
||||||
var items []string
|
|
||||||
if err := json.Unmarshal([]byte(C.GoString(jsonInput)), &items); err != nil {
|
|
||||||
return C.CString("[]")
|
|
||||||
}
|
|
||||||
result := core.ProcessItems(items, core.ToUpper)
|
|
||||||
out, _ := json.Marshal(result)
|
|
||||||
return C.CString(string(out))
|
|
||||||
}
|
|
||||||
|
|
||||||
//export GoFilterNonEmpty
|
|
||||||
func GoFilterNonEmpty(jsonInput *C.char) *C.char {
|
|
||||||
var items []string
|
|
||||||
if err := json.Unmarshal([]byte(C.GoString(jsonInput)), &items); err != nil {
|
|
||||||
return C.CString("[]")
|
|
||||||
}
|
|
||||||
result := core.FilterNonEmpty(items)
|
|
||||||
out, _ := json.Marshal(result)
|
|
||||||
return C.CString(string(out))
|
|
||||||
}
|
|
||||||
|
|
||||||
//export GoSafeDivide
|
|
||||||
func GoSafeDivide(a, b C.double) *C.char {
|
|
||||||
result := core.SafeDivide(float64(a), float64(b))
|
|
||||||
if result.IsErr() {
|
|
||||||
return C.CString(`{"error":"` + result.Error().Error() + `"}`)
|
|
||||||
}
|
|
||||||
out, _ := json.Marshal(map[string]float64{"value": result.Unwrap()})
|
|
||||||
return C.CString(string(out))
|
|
||||||
}
|
|
||||||
|
|
||||||
//export GoFree
|
|
||||||
func GoFree(ptr *C.char) {
|
|
||||||
C.free(unsafe.Pointer(ptr))
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {}
|
|
||||||
GOEOF
|
|
||||||
|
|
||||||
# --- python/bindings/__init__.py — Wrapper ctypes auto-generado ---
|
|
||||||
log_step "Generando python/bindings/ (ctypes wrapper)..."
|
|
||||||
|
|
||||||
# Nombre de la shared library según OS
|
|
||||||
SO_NAME="lib${MODULE_NAME}.so"
|
|
||||||
|
|
||||||
cat > "$PROJECT_DIR/python/bindings/__init__.py" << PYEOF
|
|
||||||
"""
|
|
||||||
Auto-generated Python bindings for $MODULE_NAME.
|
|
||||||
Uses ctypes to call Go functions compiled as C shared library.
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
from bindings import to_upper, process_items, filter_non_empty, safe_divide
|
|
||||||
"""
|
|
||||||
import ctypes
|
|
||||||
import json
|
|
||||||
import os
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
# Localizar la shared library
|
|
||||||
_LIB_DIR = Path(__file__).parent.parent.parent / "build"
|
|
||||||
_LIB_NAME = "$SO_NAME"
|
|
||||||
_LIB_PATH = _LIB_DIR / _LIB_NAME
|
|
||||||
|
|
||||||
if not _LIB_PATH.exists():
|
|
||||||
raise FileNotFoundError(
|
|
||||||
f"Shared library not found at {_LIB_PATH}. "
|
|
||||||
f"Run 'make build' in the project root first."
|
|
||||||
)
|
|
||||||
|
|
||||||
_lib = ctypes.CDLL(str(_LIB_PATH))
|
|
||||||
|
|
||||||
# --- Configurar tipos de retorno ---
|
|
||||||
_lib.GoToUpper.argtypes = [ctypes.c_char_p]
|
|
||||||
_lib.GoToUpper.restype = ctypes.c_char_p
|
|
||||||
|
|
||||||
_lib.GoProcessItems.argtypes = [ctypes.c_char_p]
|
|
||||||
_lib.GoProcessItems.restype = ctypes.c_char_p
|
|
||||||
|
|
||||||
_lib.GoFilterNonEmpty.argtypes = [ctypes.c_char_p]
|
|
||||||
_lib.GoFilterNonEmpty.restype = ctypes.c_char_p
|
|
||||||
|
|
||||||
_lib.GoSafeDivide.argtypes = [ctypes.c_double, ctypes.c_double]
|
|
||||||
_lib.GoSafeDivide.restype = ctypes.c_char_p
|
|
||||||
|
|
||||||
_lib.GoFree.argtypes = [ctypes.c_char_p]
|
|
||||||
_lib.GoFree.restype = None
|
|
||||||
|
|
||||||
|
|
||||||
def to_upper(text: str) -> str:
|
|
||||||
"""Convert text to uppercase using Go core."""
|
|
||||||
result = _lib.GoToUpper(text.encode("utf-8"))
|
|
||||||
return result.decode("utf-8")
|
|
||||||
|
|
||||||
|
|
||||||
def process_items(items: list[str]) -> list[str]:
|
|
||||||
"""Process items through Go pipeline (ToUpper transformation)."""
|
|
||||||
input_json = json.dumps(items).encode("utf-8")
|
|
||||||
result = _lib.GoProcessItems(input_json)
|
|
||||||
return json.loads(result.decode("utf-8"))
|
|
||||||
|
|
||||||
|
|
||||||
def filter_non_empty(items: list[str]) -> list[str]:
|
|
||||||
"""Filter empty strings using Go core."""
|
|
||||||
input_json = json.dumps(items).encode("utf-8")
|
|
||||||
result = _lib.GoFilterNonEmpty(input_json)
|
|
||||||
return json.loads(result.decode("utf-8"))
|
|
||||||
|
|
||||||
|
|
||||||
def safe_divide(a: float, b: float) -> float:
|
|
||||||
"""Safe division using Go Result type. Raises ValueError on division by zero."""
|
|
||||||
result = _lib.GoSafeDivide(ctypes.c_double(a), ctypes.c_double(b))
|
|
||||||
data = json.loads(result.decode("utf-8"))
|
|
||||||
if "error" in data:
|
|
||||||
raise ValueError(data["error"])
|
|
||||||
return data["value"]
|
|
||||||
PYEOF
|
|
||||||
|
|
||||||
# --- python/example.py ---
|
|
||||||
cat > "$PROJECT_DIR/python/example.py" << PYEOF
|
|
||||||
"""Example usage of $MODULE_NAME Go bindings from Python."""
|
|
||||||
from bindings import to_upper, process_items, filter_non_empty, safe_divide
|
|
||||||
|
|
||||||
# String transformation
|
|
||||||
print(to_upper("hello from go")) # HELLO FROM GO
|
|
||||||
|
|
||||||
# Batch processing via Go's MapSlice
|
|
||||||
items = ["hello", "world", "from", "go"]
|
|
||||||
print(process_items(items)) # ["HELLO", "WORLD", "FROM", "GO"]
|
|
||||||
|
|
||||||
# Filtering via Go's FilterSlice
|
|
||||||
mixed = ["hello", "", "world", " ", "go"]
|
|
||||||
print(filter_non_empty(mixed)) # ["hello", "world", "go"]
|
|
||||||
|
|
||||||
# Safe division with Result[T] error handling
|
|
||||||
print(safe_divide(10.0, 3.0)) # 3.333...
|
|
||||||
try:
|
|
||||||
safe_divide(10.0, 0.0)
|
|
||||||
except ValueError as e:
|
|
||||||
print(f"Caught: {e}") # Caught: division by zero
|
|
||||||
PYEOF
|
|
||||||
|
|
||||||
# --- core/transform_test.go ---
|
|
||||||
log_step "Generando tests..."
|
|
||||||
cat > "$PROJECT_DIR/core/transform_test.go" << 'GOEOF'
|
|
||||||
package core
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestToUpper(t *testing.T) {
|
|
||||||
if got := ToUpper("hello"); got != "HELLO" {
|
|
||||||
t.Errorf("ToUpper(\"hello\") = %q, want %q", got, "HELLO")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilterNonEmpty(t *testing.T) {
|
|
||||||
items := []string{"hello", "", "world", " ", "go"}
|
|
||||||
result := FilterNonEmpty(items)
|
|
||||||
if len(result) != 3 {
|
|
||||||
t.Errorf("FilterNonEmpty got %d items, want 3", len(result))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSafeDivide(t *testing.T) {
|
|
||||||
ok := SafeDivide(10, 2)
|
|
||||||
if ok.IsErr() {
|
|
||||||
t.Error("SafeDivide(10, 2) should not error")
|
|
||||||
}
|
|
||||||
if ok.Unwrap() != 5.0 {
|
|
||||||
t.Errorf("SafeDivide(10, 2) = %f, want 5.0", ok.Unwrap())
|
|
||||||
}
|
|
||||||
|
|
||||||
err := SafeDivide(10, 0)
|
|
||||||
if !err.IsErr() {
|
|
||||||
t.Error("SafeDivide(10, 0) should error")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
GOEOF
|
|
||||||
|
|
||||||
# --- Makefile ---
|
|
||||||
log_step "Generando Makefile..."
|
|
||||||
cat > "$PROJECT_DIR/Makefile" << MKEOF
|
|
||||||
.PHONY: build test clean python dev
|
|
||||||
|
|
||||||
MODULE_NAME := $MODULE_NAME
|
|
||||||
BUILD_DIR := build
|
|
||||||
SO_NAME := $SO_NAME
|
|
||||||
|
|
||||||
## build: Compila la shared library (.so) para Python
|
|
||||||
build:
|
|
||||||
@mkdir -p \$(BUILD_DIR)
|
|
||||||
cd export && CGO_ENABLED=1 go build -buildmode=c-shared -o ../\$(BUILD_DIR)/\$(SO_NAME) .
|
|
||||||
@echo "✓ Built \$(BUILD_DIR)/\$(SO_NAME)"
|
|
||||||
|
|
||||||
## test: Ejecuta tests de Go
|
|
||||||
test:
|
|
||||||
go test ./core/... ./shell/... -v
|
|
||||||
|
|
||||||
## python: Compila y ejecuta ejemplo Python
|
|
||||||
python: build
|
|
||||||
cd python && python3 example.py
|
|
||||||
|
|
||||||
## clean: Limpia artefactos
|
|
||||||
clean:
|
|
||||||
rm -rf \$(BUILD_DIR)
|
|
||||||
find . -name "__pycache__" -type d -exec rm -rf {} + 2>/dev/null || true
|
|
||||||
|
|
||||||
## dev: Tests + build en un paso
|
|
||||||
dev: test build
|
|
||||||
@echo "✓ Ready — run 'make python' to test bindings"
|
|
||||||
|
|
||||||
## tidy: go mod tidy
|
|
||||||
tidy:
|
|
||||||
go mod tidy
|
|
||||||
|
|
||||||
## help: Muestra esta ayuda
|
|
||||||
help:
|
|
||||||
@grep -E '^## ' Makefile | sed 's/## //' | column -t -s ':'
|
|
||||||
MKEOF
|
|
||||||
|
|
||||||
# --- .gitignore ---
|
|
||||||
cat > "$PROJECT_DIR/.gitignore" << 'EOF'
|
|
||||||
build/
|
|
||||||
*.so
|
|
||||||
*.h
|
|
||||||
*.dylib
|
|
||||||
*.dll
|
|
||||||
__pycache__/
|
|
||||||
*.pyc
|
|
||||||
.pytest_cache/
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# --- go mod tidy ---
|
|
||||||
log_step "Ejecutando go mod tidy..."
|
|
||||||
cd "$PROJECT_DIR"
|
|
||||||
if [[ -f "go.work" ]]; then
|
|
||||||
go mod tidy 2>/dev/null || log_warn "go mod tidy falló — revisa el go.work"
|
|
||||||
else
|
|
||||||
go mod tidy 2>/dev/null || log_warn "go mod tidy falló — DevFactory no está disponible"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# --- Resumen ---
|
|
||||||
echo ""
|
|
||||||
log_ok "Módulo '$MODULE_NAME' creado en $PROJECT_DIR"
|
|
||||||
echo ""
|
|
||||||
echo -e "${CYAN}Estructura:${NC}"
|
|
||||||
echo " $MODULE_NAME/"
|
|
||||||
echo " ├── core/ — Funciones puras (sin side effects)"
|
|
||||||
echo " ├── shell/ — Operaciones I/O con Result[T]"
|
|
||||||
echo " ├── export/ — Funciones exportadas via CGO"
|
|
||||||
echo " ├── python/bindings — Wrapper ctypes auto-generado"
|
|
||||||
echo " ├── Makefile — build, test, python, clean"
|
|
||||||
echo " └── go.work — Enlace a DevFactory"
|
|
||||||
echo ""
|
|
||||||
echo -e "${CYAN}Comandos:${NC}"
|
|
||||||
echo " make test — Ejecutar tests Go"
|
|
||||||
echo " make build — Compilar shared library"
|
|
||||||
echo " make python — Testear bindings Python"
|
|
||||||
echo " make dev — Test + build en un paso"
|
|
||||||
echo ""
|
|
||||||
echo "STATUS: READY"
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
---
|
|
||||||
name: issues-status
|
|
||||||
description: Dashboard global de issues en todos los workspaces con métricas y filtros
|
|
||||||
argument-hint: [workspace] [--status pending] [--tag tag] [--export json|csv]
|
|
||||||
disable-model-invocation: true
|
|
||||||
user-invocable: true
|
|
||||||
allowed-tools: Bash, Read
|
|
||||||
---
|
|
||||||
|
|
||||||
# issues-status
|
|
||||||
|
|
||||||
Muestra dashboard global de todas las issues con métricas, filtros y sugerencias.
|
|
||||||
|
|
||||||
## Sintaxis
|
|
||||||
|
|
||||||
```bash
|
|
||||||
/issues-status # Dashboard global
|
|
||||||
/issues-status <workspace> # Detalle de workspace
|
|
||||||
/issues-status --status pending # Filtrar por estado
|
|
||||||
/issues-status --tag backend # Filtrar por tag
|
|
||||||
/issues-status --export json # Exportar
|
|
||||||
```
|
|
||||||
|
|
||||||
## Flujo
|
|
||||||
|
|
||||||
### 1. Parsear argumentos
|
|
||||||
|
|
||||||
- Primer arg (sin --): `filterWorkspace`
|
|
||||||
- `--status <value>`: pending | in_progress | completed
|
|
||||||
- `--tag <value>`: filtrar por tag
|
|
||||||
- `--export <format>`: json | csv
|
|
||||||
|
|
||||||
### 2. Ejecutar dashboard
|
|
||||||
|
|
||||||
Llama `app.IssuesDashboardCommand(config, filterWorkspace, filterStatus, filterTag, exportFormat)`
|
|
||||||
|
|
||||||
### 3. Modo interactivo (dashboard global)
|
|
||||||
|
|
||||||
Si no hay filtros:
|
|
||||||
1. Mostrar dashboard con sugerencias
|
|
||||||
2. Preguntar: "¿Ver detalle de un workspace? (nombre o 'n')"
|
|
||||||
3. Si responde nombre: mostrar detalle
|
|
||||||
4. Si responde 'n': terminar
|
|
||||||
|
|
||||||
### Comandos sugeridos
|
|
||||||
|
|
||||||
```
|
|
||||||
Commands:
|
|
||||||
/issues-status <workspace>
|
|
||||||
/issues-status --status pending
|
|
||||||
/fix-issue <issue>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Manejo de errores
|
|
||||||
|
|
||||||
- Si no hay workspaces: sugerir crear o sincronizar
|
|
||||||
- Si no hay issues: mostrar dashboard vacío con sugerencias
|
|
||||||
@@ -0,0 +1,268 @@
|
|||||||
|
---
|
||||||
|
name: parallel-fix-issues
|
||||||
|
description: >
|
||||||
|
Implementar múltiples issues en paralelo. Analiza dependencias entre issues pendientes,
|
||||||
|
crea git worktrees aislados, lanza agentes concurrentes para cada issue, verifica
|
||||||
|
resultados (build + tests) e integra todo a master en orden.
|
||||||
|
allowed-tools: Bash Read Write Edit Grep Glob Agent
|
||||||
|
argument-hint: "[issue-numbers... | all]"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Parallel Fix Issues
|
||||||
|
|
||||||
|
Skill para implementar múltiples issues simultáneamente usando git worktrees y agentes paralelos.
|
||||||
|
|
||||||
|
## Inputs
|
||||||
|
|
||||||
|
- `$ARGUMENTS`: lista de issue numbers (ej: `0026 0027 0031`) o `all` para todos los pendientes.
|
||||||
|
- Si no hay argumentos, preguntar al usuario qué issues quiere procesar.
|
||||||
|
|
||||||
|
## Proceso completo
|
||||||
|
|
||||||
|
### Fase 1: Análisis de dependencias
|
||||||
|
|
||||||
|
Lanzar un **Agent** (subagent_type: `Explore`) para analizar los issues y producir un plan de ejecución.
|
||||||
|
|
||||||
|
El agente debe:
|
||||||
|
|
||||||
|
1. Leer `dev/issues/README.md` y filtrar los issues pendientes
|
||||||
|
2. Si `$ARGUMENTS` no es `all`, filtrar solo los issues solicitados
|
||||||
|
3. Para cada issue pendiente, leer el archivo completo y extraer:
|
||||||
|
- **Objetivo** (resumen)
|
||||||
|
- **Prerequisitos** y dependencias explícitas (ej: "requiere issue 0026")
|
||||||
|
- **Archivos afectados** (para detectar conflictos potenciales entre issues)
|
||||||
|
4. Construir un **grafo de dependencias** y agrupar en **waves** (oleadas):
|
||||||
|
- Wave 1: issues sin dependencias entre sí y sin dependencias pendientes
|
||||||
|
- Wave 2: issues que dependen de wave 1
|
||||||
|
- Wave N: etc.
|
||||||
|
5. Dentro de cada wave, identificar **conflictos potenciales** (dos issues que tocan los mismos archivos)
|
||||||
|
6. Devolver el resultado en este formato exacto:
|
||||||
|
|
||||||
|
```
|
||||||
|
WAVE 1 (paralelo):
|
||||||
|
- <NNNN>-<slug> — <objetivo resumido> — archivos: <lista>
|
||||||
|
- <NNNN>-<slug> — <objetivo resumido> — archivos: <lista>
|
||||||
|
|
||||||
|
WAVE 2 (paralelo, después de wave 1):
|
||||||
|
- <NNNN>-<slug> — <objetivo resumido> — depende de: <NNNN>
|
||||||
|
|
||||||
|
CONFLICTOS POTENCIALES:
|
||||||
|
- <NNNN> y <NNNN> tocan <archivo> — riesgo de merge conflict
|
||||||
|
|
||||||
|
ISSUES EXCLUIDOS:
|
||||||
|
- <NNNN>-<slug> — razón (dependencia externa no resuelta, etc.)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Mostrar el resultado al usuario y pedir confirmación** antes de continuar. El usuario puede:
|
||||||
|
- Aprobar el plan tal cual
|
||||||
|
- Excluir issues específicos
|
||||||
|
- Reordenar waves
|
||||||
|
|
||||||
|
### Fase 2: Setup de worktrees
|
||||||
|
|
||||||
|
Una vez aprobado el plan, crear los worktrees.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
.claude/skills/parallel-fix-issues/scripts/setup-worktrees.sh <slug-1> <slug-2> ...
|
||||||
|
```
|
||||||
|
|
||||||
|
El script crea un worktree por issue en `worktrees/<slug>/`, cada uno en su propia branch `issue/<slug>`.
|
||||||
|
|
||||||
|
**Verificar** que todos los worktrees se crearon correctamente:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git worktree list
|
||||||
|
```
|
||||||
|
|
||||||
|
### Fase 3: Ejecución paralela por waves
|
||||||
|
|
||||||
|
Para cada wave, lanzar **Agents en paralelo** (un Agent por issue, todos en el mismo mensaje para ejecución concurrente).
|
||||||
|
|
||||||
|
**CRÍTICO**: Lanzar todos los agentes de una wave en una sola respuesta con múltiples tool calls. NO lanzar de uno en uno.
|
||||||
|
|
||||||
|
**PERMISOS**: Todas las llamadas Bash de los agentes deben usar `dangerouslyDisableSandbox: true` para evitar prompts de permisos que bloqueen la ejecución paralela. Indicar esto explícitamente en el prompt de cada agente.
|
||||||
|
|
||||||
|
El prompt de cada agente debe incluir:
|
||||||
|
|
||||||
|
1. **Ruta absoluta del worktree**: `/home/ubuntu/CodeProyects/agents_and_robots/worktrees/<slug>`
|
||||||
|
2. **Contenido completo del issue** (copiar el markdown entero)
|
||||||
|
3. **Instrucciones de ejecución** (ver template abajo)
|
||||||
|
|
||||||
|
#### Template de prompt para cada agente
|
||||||
|
|
||||||
|
```
|
||||||
|
Eres un agente de desarrollo implementando el issue <NNNN>-<slug>.
|
||||||
|
|
||||||
|
## Directorio de trabajo
|
||||||
|
|
||||||
|
Worktree: /home/ubuntu/CodeProyects/agents_and_robots/worktrees/<slug>
|
||||||
|
|
||||||
|
Usa SIEMPRE esta ruta como prefijo en paths absolutos.
|
||||||
|
Variable de conveniencia para comandos:
|
||||||
|
W=/home/ubuntu/CodeProyects/agents_and_robots/worktrees/<slug>
|
||||||
|
|
||||||
|
## Permisos
|
||||||
|
|
||||||
|
IMPORTANTE: En TODAS tus llamadas al tool Bash, usa el parámetro `dangerouslyDisableSandbox: true`.
|
||||||
|
Esto es necesario porque estás ejecutando en paralelo con otros agentes y no hay usuario interactivo
|
||||||
|
para aprobar permisos. Ejemplo:
|
||||||
|
|
||||||
|
Bash({ command: "cd $W && go build -tags goolm ./...", dangerouslyDisableSandbox: true })
|
||||||
|
|
||||||
|
## Issue a implementar
|
||||||
|
|
||||||
|
<PEGAR CONTENIDO COMPLETO DEL ISSUE AQUÍ>
|
||||||
|
|
||||||
|
## Instrucciones
|
||||||
|
|
||||||
|
Sigue este flujo estrictamente:
|
||||||
|
|
||||||
|
1. **Leer el issue** — ya lo tienes arriba, entiende objetivo, tareas y arquitectura.
|
||||||
|
|
||||||
|
2. **Implementar todas las tareas** en orden:
|
||||||
|
- Respetar pure core / impure shell (pkg/ puro, shell/ impuro)
|
||||||
|
- Hacer commits atómicos por bloque lógico
|
||||||
|
- Prefijos: feat:, fix:, test:, docs:, refactor:, chore:
|
||||||
|
- NO hacer commits WIP ni código a medias
|
||||||
|
- Compilar frecuentemente:
|
||||||
|
Bash({ command: "cd $W && go build -tags goolm ./...", dangerouslyDisableSandbox: true })
|
||||||
|
|
||||||
|
3. **Tests obligatorios**:
|
||||||
|
- Escribir tests para todo código nuevo
|
||||||
|
- Ejecutar:
|
||||||
|
Bash({ command: "cd $W && go test -tags goolm ./...", dangerouslyDisableSandbox: true })
|
||||||
|
- NO continuar si los tests fallan
|
||||||
|
|
||||||
|
4. **Cerrar el issue** — solo mover el archivo, NO tocar README:
|
||||||
|
- Bash({ command: "cd $W && git mv dev/issues/<NNNN>-<slug>.md dev/issues/completed/", dangerouslyDisableSandbox: true })
|
||||||
|
- Commit: docs: cerrar issue <NNNN>
|
||||||
|
IMPORTANTE: usar `git mv` (no `mv` + `git add`) para que git registre el movimiento.
|
||||||
|
IMPORTANTE: NO modificar dev/issues/README.md — lo hace el orquestador después del merge
|
||||||
|
para evitar conflictos entre agentes paralelos.
|
||||||
|
|
||||||
|
5. **NO hacer merge a master, NO hacer push.** La integración la maneja el orquestador.
|
||||||
|
|
||||||
|
6. **Reportar resultado** al final:
|
||||||
|
- ÉXITO: qué se implementó, cuántos commits, tests pasando
|
||||||
|
- FALLO: qué falló, en qué paso, qué queda pendiente
|
||||||
|
```
|
||||||
|
|
||||||
|
**Esperar** a que todos los agentes de la wave terminen antes de pasar a la siguiente wave.
|
||||||
|
|
||||||
|
### Fase 4: Verificación
|
||||||
|
|
||||||
|
Después de cada wave, verificar TODOS los worktrees completados:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
.claude/skills/parallel-fix-issues/scripts/verify-worktree.sh worktrees/<slug>
|
||||||
|
```
|
||||||
|
|
||||||
|
El script verifica:
|
||||||
|
- `go build -tags goolm ./...` — compila sin errores
|
||||||
|
- `go test -tags goolm ./...` — tests pasan
|
||||||
|
- Issue movido a `dev/issues/completed/`
|
||||||
|
- Al menos 1 commit en la branch
|
||||||
|
|
||||||
|
**Si un worktree falla verificación**:
|
||||||
|
1. Reportar al usuario qué falló
|
||||||
|
2. Preguntar si quiere: (a) intentar arreglar, (b) excluir ese issue, (c) abortar todo
|
||||||
|
3. Si se excluye, marcar para no integrar
|
||||||
|
|
||||||
|
### Fase 5: Integración a master
|
||||||
|
|
||||||
|
Una vez todas las waves verificadas, integrar a master **en orden de waves** (wave 1 primero, luego wave 2, etc.).
|
||||||
|
|
||||||
|
```bash
|
||||||
|
.claude/skills/parallel-fix-issues/scripts/integrate-worktrees.sh <slug-1> <slug-2> ...
|
||||||
|
```
|
||||||
|
|
||||||
|
El script hace para cada branch:
|
||||||
|
1. `git checkout master`
|
||||||
|
2. `git merge --no-ff issue/<slug>` con mensaje descriptivo
|
||||||
|
3. Si hay **merge conflict**: PARAR e informar al usuario
|
||||||
|
|
||||||
|
**Después de cada merge**, re-verificar que master compila:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go build -tags goolm ./... && go test -tags goolm ./...
|
||||||
|
```
|
||||||
|
|
||||||
|
Si falla después de un merge, PARAR e informar — no continuar con más merges.
|
||||||
|
|
||||||
|
### Fase 6: Actualizar README de issues
|
||||||
|
|
||||||
|
Después de integrar TODOS los issues exitosos, actualizar `dev/issues/README.md` **una sola vez** desde master.
|
||||||
|
Esto evita conflictos: los agentes paralelos solo mueven archivos, el orquestador actualiza el índice.
|
||||||
|
|
||||||
|
Para cada issue integrado:
|
||||||
|
1. Cambiar el link de `[<NNNN>-<slug>.md](<NNNN>-<slug>.md)` a `[<NNNN>-<slug>.md](completed/<NNNN>-<slug>.md)`
|
||||||
|
2. Cambiar el estado de `pendiente` a `completado`
|
||||||
|
|
||||||
|
Hacer un solo commit:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add dev/issues/README.md
|
||||||
|
git commit -m "docs: actualizar README de issues — marcar <N> issues como completados"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Fase 7: Limpieza
|
||||||
|
|
||||||
|
Si todo fue exitoso:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Eliminar worktrees y branches
|
||||||
|
for slug in <slugs...>; do
|
||||||
|
git worktree remove "worktrees/${slug}" 2>/dev/null
|
||||||
|
git branch -d "issue/${slug}" 2>/dev/null
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
### Fase 8: Reporte final
|
||||||
|
|
||||||
|
Mostrar al usuario un resumen:
|
||||||
|
|
||||||
|
```
|
||||||
|
## Resultado de parallel-fix-issues
|
||||||
|
|
||||||
|
### Issues completados
|
||||||
|
- ✓ 0026-split-runtime — 5 commits
|
||||||
|
- ✓ 0027-prune-config-schema — 3 commits
|
||||||
|
- ✓ 0031-expand-file-tools — 7 commits
|
||||||
|
|
||||||
|
### Issues fallidos
|
||||||
|
- ✗ 0029-core-tests — falló en fase de tests (excluido)
|
||||||
|
|
||||||
|
### Estado de master
|
||||||
|
- Build: OK
|
||||||
|
- Tests: OK (142 passed)
|
||||||
|
- Commits nuevos: 18
|
||||||
|
|
||||||
|
### Siguiente paso
|
||||||
|
Ejecutar: git push
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notas importantes
|
||||||
|
|
||||||
|
- **Siempre compilar con `-tags goolm`**
|
||||||
|
- **Siempre usar `dangerouslyDisableSandbox: true`** en todas las llamadas Bash de los agentes paralelos
|
||||||
|
- **Nunca hacer push automáticamente** — el usuario decide cuándo pushear
|
||||||
|
- **Si hay merge conflicts**, parar y pedir intervención manual
|
||||||
|
- **Un worktree = un issue = una branch** — nunca mezclar
|
||||||
|
- Los worktrees se crean desde `master` actualizado
|
||||||
|
- La carpeta `worktrees/` está en `.gitignore`
|
||||||
|
- Issues con dependencias externas no resueltas se excluyen automáticamente
|
||||||
|
- **README centralizado**: los agentes NO tocan `dev/issues/README.md` — solo el orquestador lo actualiza después del merge, en un solo commit. Esto evita merge conflicts entre agentes paralelos
|
||||||
|
- **`git mv` para cerrar issues**: usar `git mv` (no `mv` + `git add`) para mover issues a `completed/`
|
||||||
|
|
||||||
|
## Casos de uso
|
||||||
|
|
||||||
|
```
|
||||||
|
# Implementar todos los issues pendientes
|
||||||
|
/parallel-fix-issues all
|
||||||
|
|
||||||
|
# Implementar issues específicos
|
||||||
|
/parallel-fix-issues 0026 0027 0031
|
||||||
|
|
||||||
|
# Solo los issues de refactor
|
||||||
|
/parallel-fix-issues 0026 0027 0028
|
||||||
|
```
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# integrate-worktrees.sh — Integra branches de worktrees a master con --no-ff
|
||||||
|
#
|
||||||
|
# Uso: ./integrate-worktrees.sh <slug-1> <slug-2> ...
|
||||||
|
# Ejemplo: ./integrate-worktrees.sh 0026-split-runtime 0027-prune-config-schema
|
||||||
|
#
|
||||||
|
# Para cada slug:
|
||||||
|
# 1. git merge --no-ff issue/<slug> a master
|
||||||
|
# 2. Verificar que master compila después del merge
|
||||||
|
# 3. Si hay conflict o fallo de build, PARAR inmediatamente
|
||||||
|
#
|
||||||
|
# Los slugs deben pasarse en el orden correcto (waves ya resueltas).
|
||||||
|
# NO hace push — eso lo decide el usuario.
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
REPO_ROOT="$(git rev-parse --show-toplevel)"
|
||||||
|
|
||||||
|
if [ $# -eq 0 ]; then
|
||||||
|
echo "ERROR: se necesita al menos un slug"
|
||||||
|
echo "Uso: $0 <slug-1> <slug-2> ..."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Asegurar que estamos en master
|
||||||
|
echo "=== Cambiando a master ==="
|
||||||
|
cd "$REPO_ROOT"
|
||||||
|
git checkout master
|
||||||
|
|
||||||
|
MERGED=0
|
||||||
|
FAILED_AT=""
|
||||||
|
|
||||||
|
for slug in "$@"; do
|
||||||
|
branch="issue/${slug}"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Integrando: ${branch} ==="
|
||||||
|
|
||||||
|
# Verificar que la branch existe
|
||||||
|
if ! git show-ref --verify --quiet "refs/heads/${branch}"; then
|
||||||
|
echo "FAIL: branch ${branch} no existe"
|
||||||
|
FAILED_AT="$slug"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Merge --no-ff
|
||||||
|
if ! git merge --no-ff "$branch" -m "merge: ${branch} — implementación paralela"; then
|
||||||
|
echo ""
|
||||||
|
echo "CONFLICT: merge de ${branch} tiene conflictos"
|
||||||
|
echo "Resolver manualmente y luego continuar con los slugs restantes"
|
||||||
|
echo ""
|
||||||
|
echo "Para resolver:"
|
||||||
|
echo " 1. git status (ver archivos en conflicto)"
|
||||||
|
echo " 2. Resolver conflictos en cada archivo"
|
||||||
|
echo " 3. git add <archivos>"
|
||||||
|
echo " 4. git commit"
|
||||||
|
echo ""
|
||||||
|
echo "Slugs pendientes después de ${slug}:"
|
||||||
|
FOUND=0
|
||||||
|
for remaining in "$@"; do
|
||||||
|
if [ "$FOUND" -eq 1 ]; then
|
||||||
|
echo " - ${remaining}"
|
||||||
|
fi
|
||||||
|
if [ "$remaining" = "$slug" ]; then
|
||||||
|
FOUND=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "MERGED: ${branch}"
|
||||||
|
|
||||||
|
# Verificar que master sigue compilando
|
||||||
|
echo "--- Verificando build post-merge ---"
|
||||||
|
if ! (cd "$REPO_ROOT" && go build -tags goolm ./... 2>&1); then
|
||||||
|
echo ""
|
||||||
|
echo "FAIL: master no compila después de mergear ${branch}"
|
||||||
|
echo "Revertir con: git reset --hard HEAD~1"
|
||||||
|
echo "Investigar el problema antes de continuar."
|
||||||
|
FAILED_AT="$slug"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
echo "OK: build post-merge exitoso"
|
||||||
|
|
||||||
|
MERGED=$((MERGED + 1))
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Resumen de integración ==="
|
||||||
|
echo "Mergeados: ${MERGED} de $#"
|
||||||
|
|
||||||
|
if [ -n "$FAILED_AT" ]; then
|
||||||
|
echo "Falló en: ${FAILED_AT}"
|
||||||
|
echo ""
|
||||||
|
echo "Worktrees NO limpiados (resolver primero el fallo)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Limpieza de worktrees y branches
|
||||||
|
echo ""
|
||||||
|
echo "=== Limpieza ==="
|
||||||
|
for slug in "$@"; do
|
||||||
|
path="${REPO_ROOT}/worktrees/${slug}"
|
||||||
|
branch="issue/${slug}"
|
||||||
|
|
||||||
|
if [ -d "$path" ]; then
|
||||||
|
git worktree remove "$path" 2>/dev/null && echo "REMOVED: worktree ${path}" || echo "WARN: no se pudo eliminar worktree ${path}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
git branch -d "$branch" 2>/dev/null && echo "DELETED: branch ${branch}" || echo "WARN: no se pudo eliminar branch ${branch}"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Integración completa ==="
|
||||||
|
echo "Master tiene ${MERGED} merges nuevos."
|
||||||
|
echo ""
|
||||||
|
echo "Para publicar: git push"
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# setup-worktrees.sh — Crea git worktrees para ejecución paralela de issues
|
||||||
|
#
|
||||||
|
# Uso: ./setup-worktrees.sh <slug-1> <slug-2> ...
|
||||||
|
# Ejemplo: ./setup-worktrees.sh 0026-split-runtime 0027-prune-config-schema
|
||||||
|
#
|
||||||
|
# Cada slug genera:
|
||||||
|
# worktrees/<slug>/ (worktree completo)
|
||||||
|
# branch: issue/<slug>
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
REPO_ROOT="$(git rev-parse --show-toplevel)"
|
||||||
|
WORKTREE_DIR="${REPO_ROOT}/worktrees"
|
||||||
|
|
||||||
|
if [ $# -eq 0 ]; then
|
||||||
|
echo "ERROR: se necesita al menos un slug de issue"
|
||||||
|
echo "Uso: $0 <slug-1> <slug-2> ..."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Asegurar que master está actualizado
|
||||||
|
echo "=== Actualizando master ==="
|
||||||
|
CURRENT_BRANCH="$(git branch --show-current)"
|
||||||
|
git checkout master 2>/dev/null
|
||||||
|
git pull --rebase 2>/dev/null || echo "WARN: no se pudo pull (sin remote o sin conexión)"
|
||||||
|
|
||||||
|
# Volver a la rama original si no era master
|
||||||
|
if [ "$CURRENT_BRANCH" != "master" ] && [ -n "$CURRENT_BRANCH" ]; then
|
||||||
|
git checkout "$CURRENT_BRANCH" 2>/dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "$WORKTREE_DIR"
|
||||||
|
|
||||||
|
CREATED=0
|
||||||
|
SKIPPED=0
|
||||||
|
FAILED=0
|
||||||
|
|
||||||
|
for slug in "$@"; do
|
||||||
|
branch="issue/${slug}"
|
||||||
|
path="${WORKTREE_DIR}/${slug}"
|
||||||
|
|
||||||
|
if [ -d "$path" ]; then
|
||||||
|
echo "SKIP: worktree ya existe: ${path}"
|
||||||
|
SKIPPED=$((SKIPPED + 1))
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verificar que la branch no existe ya
|
||||||
|
if git show-ref --verify --quiet "refs/heads/${branch}" 2>/dev/null; then
|
||||||
|
echo "WARN: branch ${branch} ya existe, creando worktree desde ella"
|
||||||
|
git worktree add "$path" "$branch" 2>/dev/null || {
|
||||||
|
echo "FAIL: no se pudo crear worktree para ${slug}"
|
||||||
|
FAILED=$((FAILED + 1))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
else
|
||||||
|
echo "CREATE: worktree ${path} (branch ${branch})"
|
||||||
|
git worktree add -b "$branch" "$path" master 2>/dev/null || {
|
||||||
|
echo "FAIL: no se pudo crear worktree para ${slug}"
|
||||||
|
FAILED=$((FAILED + 1))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
|
||||||
|
CREATED=$((CREATED + 1))
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Resumen ==="
|
||||||
|
echo "Creados: ${CREATED}"
|
||||||
|
echo "Existentes: ${SKIPPED}"
|
||||||
|
echo "Fallidos: ${FAILED}"
|
||||||
|
echo ""
|
||||||
|
echo "=== Worktrees activos ==="
|
||||||
|
git worktree list
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# verify-worktree.sh — Verifica build, tests y cierre de issue en un worktree
|
||||||
|
#
|
||||||
|
# Uso: ./verify-worktree.sh <worktree-path>
|
||||||
|
# Ejemplo: ./verify-worktree.sh worktrees/0026-split-runtime
|
||||||
|
#
|
||||||
|
# Checks:
|
||||||
|
# 1. El worktree existe y tiene commits propios
|
||||||
|
# 2. go build -tags goolm ./... compila
|
||||||
|
# 3. go test -tags goolm ./... pasa
|
||||||
|
# 4. El issue fue movido a completed/
|
||||||
|
#
|
||||||
|
# Exit codes:
|
||||||
|
# 0 = todo OK
|
||||||
|
# 1 = error de argumento
|
||||||
|
# 2 = build falló
|
||||||
|
# 3 = tests fallaron
|
||||||
|
# 4 = issue no cerrado
|
||||||
|
# 5 = sin commits propios
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [ $# -lt 1 ]; then
|
||||||
|
echo "ERROR: se necesita el path del worktree"
|
||||||
|
echo "Uso: $0 <worktree-path>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
WORKTREE="$1"
|
||||||
|
|
||||||
|
# Resolver path absoluto
|
||||||
|
if [[ "$WORKTREE" != /* ]]; then
|
||||||
|
REPO_ROOT="$(git rev-parse --show-toplevel)"
|
||||||
|
WORKTREE="${REPO_ROOT}/${WORKTREE}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -d "$WORKTREE" ]; then
|
||||||
|
echo "ERROR: worktree no encontrado: ${WORKTREE}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
SLUG="$(basename "$WORKTREE")"
|
||||||
|
echo "=== Verificando: ${SLUG} ==="
|
||||||
|
|
||||||
|
# 1. Verificar commits propios
|
||||||
|
echo "--- Commits propios ---"
|
||||||
|
COMMIT_COUNT=$(cd "$WORKTREE" && git log master..HEAD --oneline 2>/dev/null | wc -l)
|
||||||
|
if [ "$COMMIT_COUNT" -eq 0 ]; then
|
||||||
|
echo "FAIL: sin commits propios en la branch"
|
||||||
|
exit 5
|
||||||
|
fi
|
||||||
|
echo "OK: ${COMMIT_COUNT} commits desde master"
|
||||||
|
cd "$WORKTREE" && git log master..HEAD --oneline
|
||||||
|
|
||||||
|
# 2. Build
|
||||||
|
echo ""
|
||||||
|
echo "--- Build ---"
|
||||||
|
if (cd "$WORKTREE" && go build -tags goolm ./... 2>&1); then
|
||||||
|
echo "OK: build exitoso"
|
||||||
|
else
|
||||||
|
echo "FAIL: build falló"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 3. Tests
|
||||||
|
echo ""
|
||||||
|
echo "--- Tests ---"
|
||||||
|
if (cd "$WORKTREE" && go test -tags goolm ./... 2>&1); then
|
||||||
|
echo "OK: tests pasaron"
|
||||||
|
else
|
||||||
|
echo "FAIL: tests fallaron"
|
||||||
|
exit 3
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 4. Issue cerrado (movido a completed/)
|
||||||
|
echo ""
|
||||||
|
echo "--- Cierre de issue ---"
|
||||||
|
COMPLETED_FILES=$(cd "$WORKTREE" && git diff --name-only master -- dev/issues/completed/ 2>/dev/null | wc -l)
|
||||||
|
if [ "$COMPLETED_FILES" -gt 0 ]; then
|
||||||
|
echo "OK: issue movido a completed/"
|
||||||
|
cd "$WORKTREE" && git diff --name-only master -- dev/issues/completed/
|
||||||
|
else
|
||||||
|
echo "WARN: no se detectó issue movido a completed/ (verificar manualmente)"
|
||||||
|
# No es un error fatal — puede que el issue no siga la convención exacta
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== RESULTADO: ${SLUG} — OK ==="
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
---
|
|
||||||
name: parallel-issues
|
|
||||||
description: Analiza issues y genera plan de ejecución paralela en PARALLEL_EXECUTION_ORDER.md
|
|
||||||
argument-hint: [--dry-run]
|
|
||||||
disable-model-invocation: true
|
|
||||||
user-invocable: true
|
|
||||||
allowed-tools: Bash, Read, Write
|
|
||||||
---
|
|
||||||
|
|
||||||
# parallel-issues
|
|
||||||
|
|
||||||
Analiza issues pendientes y genera plan de ejecución paralela agrupando issues independientes.
|
|
||||||
|
|
||||||
## Sintaxis
|
|
||||||
|
|
||||||
```bash
|
|
||||||
/parallel-issues # Genera archivo
|
|
||||||
/parallel-issues --dry-run # Solo muestra análisis
|
|
||||||
```
|
|
||||||
|
|
||||||
## Cuándo usar
|
|
||||||
|
|
||||||
- Identificar issues paralelizables sin conflictos
|
|
||||||
- Planificar desarrollo con múltiples worktrees
|
|
||||||
- Antes de sesiones intensivas de desarrollo
|
|
||||||
|
|
||||||
## Flujo
|
|
||||||
|
|
||||||
### 1. Detectar contexto
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Proyecto padre o hijo?
|
|
||||||
if [[ "$PWD" == *"/workspaces/"* ]]; then
|
|
||||||
PROJECT_TYPE="child"
|
|
||||||
else
|
|
||||||
PROJECT_TYPE="parent"
|
|
||||||
fi
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Listar issues pendientes
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ls -1 dev/issues/*.md | grep -E '[0-9]{4}-.*\.md$' | sort
|
|
||||||
```
|
|
||||||
|
|
||||||
Para cada issue extraer:
|
|
||||||
- Número, título, estado
|
|
||||||
- Archivos mencionados
|
|
||||||
- Dependencias explícitas (#NNNN)
|
|
||||||
|
|
||||||
### 3. Analizar conflictos
|
|
||||||
|
|
||||||
**Criterios de conflicto (NO paralelizables):**
|
|
||||||
- Archivos compartidos
|
|
||||||
- Dependencias explícitas
|
|
||||||
- Dependencias transitivas
|
|
||||||
|
|
||||||
### 4. Agrupar por independencia
|
|
||||||
|
|
||||||
Algoritmo de grafos:
|
|
||||||
- Grupo 1: Issues sin dependencias
|
|
||||||
- Grupo 2: Issues que dependen solo de Grupo 1
|
|
||||||
- etc.
|
|
||||||
|
|
||||||
### 5. Estimar tiempos
|
|
||||||
|
|
||||||
Factores:
|
|
||||||
- Cantidad de archivos
|
|
||||||
- Capa afectada (core/shell/app)
|
|
||||||
- Palabras clave (refactor, fix, nuevo)
|
|
||||||
|
|
||||||
### 6. Generar PARALLEL_EXECUTION_ORDER.md
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
# Plan de Ejecución Paralela
|
|
||||||
|
|
||||||
## Grupo 1: Issues Independientes
|
|
||||||
- Issue #0003 - ...
|
|
||||||
- Issue #0006 - ...
|
|
||||||
|
|
||||||
## Grupo 2: Dependientes de Grupo 1
|
|
||||||
- Issue #0004 - depende de #0003
|
|
||||||
|
|
||||||
## Resumen
|
|
||||||
| Métrica | Valor |
|
|
||||||
|---------|-------|
|
|
||||||
| Ahorro tiempo | 60% |
|
|
||||||
```
|
|
||||||
|
|
||||||
### 7. Mostrar resultado
|
|
||||||
|
|
||||||
```
|
|
||||||
Plan generado: PARALLEL_EXECUTION_ORDER.md
|
|
||||||
|
|
||||||
Issues analizadas: N
|
|
||||||
Grupos paralelos: M
|
|
||||||
Ahorro estimado: X%
|
|
||||||
```
|
|
||||||
|
|
||||||
## Convenciones
|
|
||||||
|
|
||||||
- Nombres de grupo: "Grupo N"
|
|
||||||
- Worktrees: `worktrees/issue-NNNN`
|
|
||||||
- Estimación en horas (redondeado a .5)
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
---
|
|
||||||
name: quick-issue
|
|
||||||
description: Crea un issue automáticamente desde TUI con detección automática de número
|
|
||||||
argument-hint: --text "descripción"
|
|
||||||
disable-model-invocation: true
|
|
||||||
user-invocable: true
|
|
||||||
allowed-tools: Bash, Read, Write, Edit
|
|
||||||
---
|
|
||||||
|
|
||||||
# quick-issue
|
|
||||||
|
|
||||||
Crea un issue rápido desde TUI. **No invocar manualmente** - es para uso automático.
|
|
||||||
|
|
||||||
## Sintaxis
|
|
||||||
|
|
||||||
```bash
|
|
||||||
/quick-issue --text "descripción del issue"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Precondiciones
|
|
||||||
|
|
||||||
- [ ] Directorio `dev/issues/` existe
|
|
||||||
- [ ] Parámetro `--text` proporcionado
|
|
||||||
- [ ] Working tree limpio
|
|
||||||
|
|
||||||
## Flujo
|
|
||||||
|
|
||||||
### 1. Determinar número
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ls -1 dev/issues/*.md | grep -E '^dev/issues/[0-9]{4}[a-z]?-' | sort -V
|
|
||||||
```
|
|
||||||
|
|
||||||
Siguiente = último número base + 1 (ignorar letras).
|
|
||||||
|
|
||||||
### 2. Generar título y slug
|
|
||||||
|
|
||||||
- Título: usar `--text` directamente
|
|
||||||
- Slug: convertir a kebab-case
|
|
||||||
|
|
||||||
### 3. Crear archivo de issue
|
|
||||||
|
|
||||||
Template minimalista con:
|
|
||||||
- Metadata básica
|
|
||||||
- Objetivo = texto del parámetro
|
|
||||||
- Tareas a completar con /fix-issue
|
|
||||||
|
|
||||||
### 4. Actualizar índice
|
|
||||||
|
|
||||||
Agregar línea en `dev/issues/README.md`.
|
|
||||||
|
|
||||||
### 5. Crear commits y mergear (sin confirmación)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git checkout -b quick/quick-issue-NNNN
|
|
||||||
git add dev/issues/NNNN-slug.md dev/issues/README.md
|
|
||||||
git commit -m "docs: crear issue NNNN-slug"
|
|
||||||
git checkout master
|
|
||||||
git merge --no-ff quick/quick-issue-NNNN
|
|
||||||
git push
|
|
||||||
git branch -d quick/quick-issue-NNNN
|
|
||||||
```
|
|
||||||
|
|
||||||
### 6. Reportar resultado
|
|
||||||
|
|
||||||
```
|
|
||||||
Issue NNNN-slug creado e integrado
|
|
||||||
|
|
||||||
Para implementar:
|
|
||||||
/fix-issue NNNN
|
|
||||||
```
|
|
||||||
|
|
||||||
## Convenciones
|
|
||||||
|
|
||||||
- Auto-detección de número
|
|
||||||
- Sin confirmación (flujo automático)
|
|
||||||
- Template minimalista
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
---
|
|
||||||
name: sort-issues
|
|
||||||
description: Analiza dependencias y genera orden de ejecución óptimo de issues
|
|
||||||
disable-model-invocation: true
|
|
||||||
user-invocable: true
|
|
||||||
allowed-tools: Bash, Read, Write
|
|
||||||
---
|
|
||||||
|
|
||||||
# sort-issues
|
|
||||||
|
|
||||||
Analiza issues, construye grafo de dependencias y muestra/genera orden de ejecución recomendado.
|
|
||||||
|
|
||||||
## Sintaxis
|
|
||||||
|
|
||||||
```bash
|
|
||||||
/sort-issues
|
|
||||||
```
|
|
||||||
|
|
||||||
## Flujo
|
|
||||||
|
|
||||||
### 1. Listar issues pendientes
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ls dev/issues/*.md | grep -E '^dev/issues/[0-9]{4}[a-z]?-.*\.md$' | sort
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Extraer dependencias de cada issue
|
|
||||||
|
|
||||||
Buscar:
|
|
||||||
- Tabla "## Dependencias"
|
|
||||||
- Línea "Bloqueada por"
|
|
||||||
- Referencias #NNNN
|
|
||||||
|
|
||||||
### 3. Construir grafo y detectar ciclos
|
|
||||||
|
|
||||||
Si hay ciclos:
|
|
||||||
```
|
|
||||||
Dependencias circulares detectadas:
|
|
||||||
0010 → 0011 → 0012 → 0010
|
|
||||||
|
|
||||||
Revisar:
|
|
||||||
- dev/issues/0010-*.md
|
|
||||||
- dev/issues/0011-*.md
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. Calcular orden topológico
|
|
||||||
|
|
||||||
Algoritmo Kahn o DFS post-order.
|
|
||||||
|
|
||||||
Desempate:
|
|
||||||
1. Número menor primero
|
|
||||||
2. Issues sin deps primero
|
|
||||||
|
|
||||||
### 5. Generar EXECUTION_ORDER.md
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
# Execution Order
|
|
||||||
|
|
||||||
## Recommended Order
|
|
||||||
1. #0001 - titulo — razón
|
|
||||||
2. #0002 - titulo — razón
|
|
||||||
|
|
||||||
## Critical Path
|
|
||||||
- #0001 → #0002, #0003
|
|
||||||
|
|
||||||
## Parallelizable Groups
|
|
||||||
### Group 1 (after #0001)
|
|
||||||
- #0002
|
|
||||||
- #0003
|
|
||||||
```
|
|
||||||
|
|
||||||
### 6. Mostrar resultado
|
|
||||||
|
|
||||||
```
|
|
||||||
Orden generado: dev/EXECUTION_ORDER.md
|
|
||||||
|
|
||||||
Issues: N
|
|
||||||
Camino crítico: #X → #Y → #Z
|
|
||||||
Grupos paralelos: M
|
|
||||||
|
|
||||||
Próxima issue: #0001 - titulo
|
|
||||||
```
|
|
||||||
|
|
||||||
## Convenciones
|
|
||||||
|
|
||||||
- Solo leer issues (no modificar)
|
|
||||||
- Detectar ambos formatos de dependencias
|
|
||||||
- Reportar ciclos claramente
|
|
||||||
+2
-2
@@ -9,7 +9,7 @@ REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|||||||
CLAUDE_DIR="$HOME/.claude"
|
CLAUDE_DIR="$HOME/.claude"
|
||||||
|
|
||||||
# Carpetas a enlazar (configuración compartible)
|
# Carpetas a enlazar (configuración compartible)
|
||||||
FOLDERS=("skills" "agents")
|
FOLDERS=("skills" "agents" "commands")
|
||||||
|
|
||||||
echo "=== Instalando configuración de Claude ==="
|
echo "=== Instalando configuración de Claude ==="
|
||||||
echo "Repositorio: $REPO_DIR/.claude"
|
echo "Repositorio: $REPO_DIR/.claude"
|
||||||
@@ -188,7 +188,7 @@ echo "=== Instalación completada ==="
|
|||||||
echo "Tus comandos y configuración ahora están sincronizados con el repositorio."
|
echo "Tus comandos y configuración ahora están sincronizados con el repositorio."
|
||||||
echo ""
|
echo ""
|
||||||
echo "Configuración instalada:"
|
echo "Configuración instalada:"
|
||||||
echo " • Skills y Agents enlazados simbólicamente"
|
echo " • Skills, Agents y Commands enlazados simbólicamente"
|
||||||
echo " • Status Line configurada con vibecoding setup"
|
echo " • Status Line configurada con vibecoding setup"
|
||||||
echo " • Settings.json enlazado (compartido entre repos)"
|
echo " • Settings.json enlazado (compartido entre repos)"
|
||||||
echo " • Backups viejos limpiados (>7 días)"
|
echo " • Backups viejos limpiados (>7 días)"
|
||||||
|
|||||||
Reference in New Issue
Block a user