chore: eliminar SKILL.md de skills obsoletos

Se eliminan los archivos SKILL.md y scripts asociados de 20 skills que
ya no se usan. Estos skills fueron reemplazados por commands (.claude/commands/)
o por skills nuevos con estructura actualizada. Limpieza necesaria para
evitar confusión entre skills activos y obsoletos.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-09 23:26:44 +02:00
parent 9da1660a59
commit b0a9e31abd
20 changed files with 0 additions and 2829 deletions
-75
View File
@@ -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/
-75
View File
@@ -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)
-74
View File
@@ -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
-439
View File
@@ -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
```
-99
View File
@@ -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
-128
View File
@@ -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]
-73
View File
@@ -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
-112
View File
@@ -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
-97
View File
@@ -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
-116
View File
@@ -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
-105
View File
@@ -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
-91
View File
@@ -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
-62
View File
@@ -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"
-53
View File
@@ -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"
-57
View File
@@ -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
-104
View File
@@ -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)
-77
View File
@@ -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
-88
View File
@@ -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