diff --git a/.claude/commands/create-issue.md b/.claude/commands/create-issue.md new file mode 100644 index 0000000..5b390d5 --- /dev/null +++ b/.claude/commands/create-issue.md @@ -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/-.md` +- Seguir directo al paso 4 + +**Si es un issue grande** (necesita desglose): +- Crear el issue principal `dev/issues/-.md` con seccion `## Desglose multi-issue` +- Crear cada sub-issue como `dev/issues/-.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 | +|-----------|------|---------|--------| +| a- | issue/a- | | pendiente | +| b- | issue/b- | | pendiente | +| ... + +### Feature flag + +Nombre: `` +Se activa en el ultimo sub-issue cuando todo esta integrado. + +### Progreso por tarea + +- [ ] **1.1** — sub-issue a +- [ ] **1.2** — sub-issue a +- [ ] **2.1** — sub-issue 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 +{ + "": { + "enabled": false, + "issue": "", + "description": "", + "added": "" + } +} +``` + +### 7. Actualizar el indice + +En `dev/issues/README.md`, agregar filas al final de la tabla. + +**Issue simple:** +```markdown +| | | [-.md](-.md) | pendiente | +``` + +**Issue multi-issue (agregar fila por cada sub-issue tambien):** +```markdown +| | | [-.md](-.md) | pendiente | +| a | (parte a) | [a-.md](a-.md) | pendiente | +| b | (parte b) | [b-.md](b-.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 ` (o `/fix-issue a`, `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 diff --git a/.claude/commands/fix-issue.md b/.claude/commands/fix-issue.md new file mode 100644 index 0000000..2022d32 --- /dev/null +++ b/.claude/commands/fix-issue.md @@ -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/-` 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/- +``` + +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/-.md dev/issues/completed/ +``` + +Actualizar `dev/issues/README.md`: + +- Link a `completed/-.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. \ No newline at end of file diff --git a/.claude/commands/git-branch.md b/.claude/commands/git-branch.md new file mode 100644 index 0000000..b2c6074 --- /dev/null +++ b/.claude/commands/git-branch.md @@ -0,0 +1,86 @@ +# Command: git branch (TBD) + +Crea una rama de trabajo. **Nunca trabajar directamente en master.** + +Soporta dos tipos de rama: +- `issue/-` — para implementar un issue existente de `dev/issues/` +- `quick/` — 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/- +``` +Ejemplo: `git checkout -b issue/0013-hot-reload` + +**Para cambios rapidos:** +```bash +git checkout -b quick/ +``` +Ejemplo: `git checkout -b quick/fix-typo-readme` + +4. Confirmar al usuario: + +``` +Rama `` creada desde master actualizado. +Puedes empezar a trabajar. Cuando termines, usa `/git-push` para integrar a master. +``` + +## Convenciones + +- **Formato de rama issue**: `issue/-` (siempre 4 digitos) +- **Formato de rama quick**: `quick/` (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). diff --git a/.claude/commands/git-push.md b/.claude/commands/git-push.md new file mode 100644 index 0000000..89ba52c --- /dev/null +++ b/.claude/commands/git-push.md @@ -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/-`. +3. **Si NO es un issue**: pedir un slug descriptivo, crear rama `quick/`. + +```bash +# Para issues: +git checkout -b issue/- +# Para cambios rapidos: +git checkout -b quick/ +``` + +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 +git commit -m ": " -m "Descripcion larga en espanol explicando que cambia, por que se hizo, impacto esperado y alcance del bloque." + +git add +git commit -m ": " -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 -m "merge: " +``` + +El merge commit debe tener formato: +- Titulo: `merge: ` +- 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 +``` + +### 8. Confirmar al usuario + +``` +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. diff --git a/.claude/skills/auto-create/SKILL.md b/.claude/skills/auto-create/SKILL.md deleted file mode 100644 index 471db22..0000000 --- a/.claude/skills/auto-create/SKILL.md +++ /dev/null @@ -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- - -# Commit -git add dev/issues/*.md dev/issues/README.md -git commit -m "docs: crear issue -" - -# Si multi-issue, commit de feature flag -git add dev/feature_flags.json -git commit -m "feat: agregar feature flag " - -# Tests (si aplican) -go test -tags goolm ./... - -# Merge -git checkout master -git merge --no-ff quick/create-issue- -git push -git branch -d quick/create-issue- -``` - -### 9. Mostrar resultado - -``` -Issue - creado e integrado automáticamente - -Para implementar: - /fix-issue -``` - -## Convenciones - -- Sin confirmación -- Mismo formato que /create-issue -- Trunk-based con rama quick/ diff --git a/.claude/skills/auto-fix/SKILL.md b/.claude/skills/auto-fix/SKILL.md deleted file mode 100644 index 21480ad..0000000 --- a/.claude/skills/auto-fix/SKILL.md +++ /dev/null @@ -1,75 +0,0 @@ ---- -name: auto-fix -description: Implementa un issue completo automáticamente SIN pedir confirmación -argument-hint: -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 -/auto-fix - -``` - -## 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/-` -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/- -m "merge: issue/-" -git push -git branch -d issue/- -``` - -### 10. Mostrar resultado - -``` -Issue 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) diff --git a/.claude/skills/cleanup-worktrees/SKILL.md b/.claude/skills/cleanup-worktrees/SKILL.md deleted file mode 100644 index e339a79..0000000 --- a/.claude/skills/cleanup-worktrees/SKILL.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -name: cleanup-worktrees -description: Limpia worktrees y ramas locales después de merge -argument-hint: | --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 # 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 --force` -4. Eliminar rama: `git branch -D ` - -### 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 diff --git a/.claude/skills/create-agent/SKILL.md b/.claude/skills/create-agent/SKILL.md deleted file mode 100644 index 87f62e0..0000000 --- a/.claude/skills/create-agent/SKILL.md +++ /dev/null @@ -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 <-.md` - -**Issue grande:** crear SOLO sub-issues `a-`, `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 -{ - "": { - "enabled": false, - "issue": "", - "description": "..." - } -} -``` - -### 7. Actualizar índice - -En `dev/issues/README.md` agregar fila(s). - -### 8. Mostrar y confirmar - -``` -Issue creado: - - -¿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-` y ejecutar flujo git. - -## Convenciones - -- Numeración continua sin saltos -- Estado inicial: pendiente -- Issues cortos (horas por rama) -- Sub-issues autocontenidos diff --git a/.claude/skills/create-issue/issue.md b/.claude/skills/create-issue/issue.md deleted file mode 100644 index 2132851..0000000 --- a/.claude/skills/create-issue/issue.md +++ /dev/null @@ -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 - - - -| 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] diff --git a/.claude/skills/create-repo/SKILL.md b/.claude/skills/create-repo/SKILL.md deleted file mode 100644 index c23e36b..0000000 --- a/.claude/skills/create-repo/SKILL.md +++ /dev/null @@ -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 diff --git a/.claude/skills/fix-issue/SKILL.md b/.claude/skills/fix-issue/SKILL.md deleted file mode 100644 index 63ac54c..0000000 --- a/.claude/skills/fix-issue/SKILL.md +++ /dev/null @@ -1,112 +0,0 @@ ---- -name: fix-issue -description: Implementa un issue completo de punta a punta con confirmación -argument-hint: -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 -/fix-issue - -``` - -## Precondiciones - -- [ ] Directorio `dev/issues/` existe -- [ ] Directorio `dev/issues/completed/` existe -- [ ] Tests configurados -- [ ] Working tree limpio - -## Flujo - -### 1. Resolver issue objetivo - -```bash -ls dev/issues/-*.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/- -``` - -### 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/-.md dev/issues/completed/ -``` - -Actualizar índice en README.md. - -### 9. Mostrar resumen y confirmar - -``` -Issue 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 diff --git a/.claude/skills/git-branch/SKILL.md b/.claude/skills/git-branch/SKILL.md deleted file mode 100644 index a6ebec6..0000000 --- a/.claude/skills/git-branch/SKILL.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -name: git-branch -description: Crea una rama de trabajo (issue/* o quick/*). Nunca trabajar directamente en master. -argument-hint: -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 -/git-branch quick -``` - -## 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/- -``` - -**Para cambios rápidos:** -```bash -git checkout -b quick/ -``` - -### 4. Confirmar creación - -```bash -git branch --show-current -``` - -Informar: -``` -Rama `` creada desde master actualizado - -Cuando termines: - /git-push -``` - -## Convenciones - -- **Formato issue**: `issue/-` (4 dígitos) -- **Formato quick**: `quick/` -- **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 diff --git a/.claude/skills/git-push/SKILL.md b/.claude/skills/git-push/SKILL.md deleted file mode 100644 index 548fba1..0000000 --- a/.claude/skills/git-push/SKILL.md +++ /dev/null @@ -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/` - -**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 -git commit -m ": " -m "" -``` - -**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 -m "merge: " -``` - -### 5. Push a remoto - -```bash -git push -``` - -### 6. Limpiar rama local - -```bash -git branch -d -``` - -### 7. Verificación final - -```bash -git log --oneline -3 -``` - -``` -Rama `` integrada a master y publicada - -Commits creados: -- -- merge: - -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 diff --git a/.claude/skills/git-recovery/SKILL.md b/.claude/skills/git-recovery/SKILL.md deleted file mode 100644 index a28c4a1..0000000 --- a/.claude/skills/git-recovery/SKILL.md +++ /dev/null @@ -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 ` -- 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 diff --git a/.claude/skills/import-repo/SKILL.md b/.claude/skills/import-repo/SKILL.md deleted file mode 100644 index 6f3b603..0000000 --- a/.claude/skills/import-repo/SKILL.md +++ /dev/null @@ -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 diff --git a/.claude/skills/init-frontend/SKILL.md b/.claude/skills/init-frontend/SKILL.md deleted file mode 100644 index 21875ac..0000000 --- a/.claude/skills/init-frontend/SKILL.md +++ /dev/null @@ -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 diff --git a/.claude/skills/init-frontend/setup-frontend.sh b/.claude/skills/init-frontend/setup-frontend.sh deleted file mode 100755 index c102acc..0000000 --- a/.claude/skills/init-frontend/setup-frontend.sh +++ /dev/null @@ -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 [--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 - - - - - - $PROJECT_NAME - - -
- - - -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( - - - , -) -TSXEOF - - cat > src/App.tsx << 'TSXEOF' -function App() { - return ( -
-

Ready

-
- ) -} - -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" diff --git a/.claude/skills/init-go-module/SKILL.md b/.claude/skills/init-go-module/SKILL.md deleted file mode 100644 index 4228712..0000000 --- a/.claude/skills/init-go-module/SKILL.md +++ /dev/null @@ -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 diff --git a/.claude/skills/init-go-module/setup-go-module.sh b/.claude/skills/init-go-module/setup-go-module.sh deleted file mode 100755 index f80f21b..0000000 --- a/.claude/skills/init-go-module/setup-go-module.sh +++ /dev/null @@ -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 [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" diff --git a/.claude/skills/issues-status/SKILL.md b/.claude/skills/issues-status/SKILL.md deleted file mode 100644 index a993f05..0000000 --- a/.claude/skills/issues-status/SKILL.md +++ /dev/null @@ -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 # 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 `: pending | in_progress | completed -- `--tag `: filtrar por tag -- `--export `: 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 - /issues-status --status pending - /fix-issue -``` - -## Manejo de errores - -- Si no hay workspaces: sugerir crear o sincronizar -- Si no hay issues: mostrar dashboard vacío con sugerencias diff --git a/.claude/skills/parallel-fix-issues/SKILL.md b/.claude/skills/parallel-fix-issues/SKILL.md new file mode 100644 index 0000000..972aada --- /dev/null +++ b/.claude/skills/parallel-fix-issues/SKILL.md @@ -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): +- - — archivos: +- - — archivos: + +WAVE 2 (paralelo, después de wave 1): +- - — depende de: + +CONFLICTOS POTENCIALES: +- y tocan — riesgo de merge conflict + +ISSUES EXCLUIDOS: +- - — 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 ... +``` + +El script crea un worktree por issue en `worktrees//`, cada uno en su propia branch `issue/`. + +**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/` +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 -. + +## Directorio de trabajo + +Worktree: /home/ubuntu/CodeProyects/agents_and_robots/worktrees/ + +Usa SIEMPRE esta ruta como prefijo en paths absolutos. +Variable de conveniencia para comandos: + W=/home/ubuntu/CodeProyects/agents_and_robots/worktrees/ + +## 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 + + + +## 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/-.md dev/issues/completed/", dangerouslyDisableSandbox: true }) + - Commit: docs: cerrar issue + 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/ +``` + +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 ... +``` + +El script hace para cada branch: +1. `git checkout master` +2. `git merge --no-ff issue/` 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 `[-.md](-.md)` a `[-.md](completed/-.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 issues como completados" +``` + +### Fase 7: Limpieza + +Si todo fue exitoso: + +```bash +# Eliminar worktrees y branches +for slug in ; 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 +``` diff --git a/.claude/skills/parallel-fix-issues/scripts/integrate-worktrees.sh b/.claude/skills/parallel-fix-issues/scripts/integrate-worktrees.sh new file mode 100755 index 0000000..16cd223 --- /dev/null +++ b/.claude/skills/parallel-fix-issues/scripts/integrate-worktrees.sh @@ -0,0 +1,117 @@ +#!/bin/bash +# integrate-worktrees.sh — Integra branches de worktrees a master con --no-ff +# +# Uso: ./integrate-worktrees.sh ... +# Ejemplo: ./integrate-worktrees.sh 0026-split-runtime 0027-prune-config-schema +# +# Para cada slug: +# 1. git merge --no-ff issue/ 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 ..." + 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 " + 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" diff --git a/.claude/skills/parallel-fix-issues/scripts/setup-worktrees.sh b/.claude/skills/parallel-fix-issues/scripts/setup-worktrees.sh new file mode 100755 index 0000000..a8854ec --- /dev/null +++ b/.claude/skills/parallel-fix-issues/scripts/setup-worktrees.sh @@ -0,0 +1,76 @@ +#!/bin/bash +# setup-worktrees.sh — Crea git worktrees para ejecución paralela de issues +# +# Uso: ./setup-worktrees.sh ... +# Ejemplo: ./setup-worktrees.sh 0026-split-runtime 0027-prune-config-schema +# +# Cada slug genera: +# worktrees// (worktree completo) +# branch: issue/ + +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 ..." + 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 diff --git a/.claude/skills/parallel-fix-issues/scripts/verify-worktree.sh b/.claude/skills/parallel-fix-issues/scripts/verify-worktree.sh new file mode 100755 index 0000000..c947b59 --- /dev/null +++ b/.claude/skills/parallel-fix-issues/scripts/verify-worktree.sh @@ -0,0 +1,88 @@ +#!/bin/bash +# verify-worktree.sh — Verifica build, tests y cierre de issue en un worktree +# +# Uso: ./verify-worktree.sh +# 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 " + 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 ===" diff --git a/.claude/skills/parallel-issues/SKILL.md b/.claude/skills/parallel-issues/SKILL.md deleted file mode 100644 index 5eec335..0000000 --- a/.claude/skills/parallel-issues/SKILL.md +++ /dev/null @@ -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) diff --git a/.claude/skills/quick-issue/SKILL.md b/.claude/skills/quick-issue/SKILL.md deleted file mode 100644 index 228af3b..0000000 --- a/.claude/skills/quick-issue/SKILL.md +++ /dev/null @@ -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 diff --git a/.claude/skills/sort-issues/SKILL.md b/.claude/skills/sort-issues/SKILL.md deleted file mode 100644 index 4b60c57..0000000 --- a/.claude/skills/sort-issues/SKILL.md +++ /dev/null @@ -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 diff --git a/install.sh b/install.sh index d8c52ce..09c1c63 100755 --- a/install.sh +++ b/install.sh @@ -9,7 +9,7 @@ REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" CLAUDE_DIR="$HOME/.claude" # Carpetas a enlazar (configuración compartible) -FOLDERS=("skills" "agents") +FOLDERS=("skills" "agents" "commands") echo "=== Instalando configuración de 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 "" 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 " • Settings.json enlazado (compartido entre repos)" echo " • Backups viejos limpiados (>7 días)"