# Regla: Git Workflow

Un historial de git limpio es documentación ejecutable del proyecto. Facilita
bisect, reverts, cherry-picks y revisiones de código. Estas reglas garantizan
que el historial sea útil y comprensible.

---

## Commits atómicos — 1 cambio lógico = 1 commit

- Un commit contiene exactamente un cambio lógico autocontenido.
  Se puede entender, revertir y aplicar de forma independiente.
- Un commit NO mezcla: refactor + nueva feature, bugfix + limpieza de código,
  cambio de deps + lógica de negocio.
- Si al escribir el mensaje de commit se necesita usar "y" o "también":
  es señal de que son dos commits.
- Commits de trabajo en progreso (`WIP`, `temp`, `fix typo`) están permitidos
  en ramas de feature, pero se squashean antes del merge.
- Commits con solo cambios de formato/whitespace: nunca mezclar con cambios
  de lógica. Hacer un commit dedicado de formateo si es necesario.
- Tamaño razonable: si un PR tiene un solo commit con 50 archivos modificados,
  el commit no es atómico — dividir en pasos lógicos.

---

## Mensajes de commit — formato imperativo, <72 chars

Formato estándar:
```
<tipo>(<scope>): <descripción en imperativo>

[cuerpo opcional — explicar POR QUÉ, no qué hace el diff]

[footer opcional — refs a tickets, breaking changes]
```

Tipos permitidos:
- `feat`: nueva funcionalidad
- `fix`: corrección de bug
- `refactor`: cambio que no agrega funcionalidad ni corrige bug
- `test`: agregar o corregir tests
- `docs`: cambios en documentación
- `chore`: actualización de deps, configuración, tooling
- `perf`: mejora de rendimiento
- `style`: cambios de formato (espacios, punto y coma, etc.)
- `ci`: cambios en pipelines de CI/CD

Reglas del mensaje:
- Primera línea: imperativo, presente, sin punto al final, <72 caracteres.
  - Mal: `Se agregó validación al formulario.`
  - Mal: `Agrega validación al formulario de registro de usuario con múltiples campos`
  - Bien: `feat(auth): agregar validación de formato de email en registro`
- El cuerpo explica el contexto y la razón del cambio, no repite el diff.
- Referenciar tickets: `Closes #123`, `Refs #456` en el footer.
- Breaking changes: `BREAKING CHANGE: descripción` en el footer.

---

## Branches descriptivas

Formato: `<tipo>/<descripcion-en-kebab-case>`

Tipos de branch:
- `feat/` — nueva feature
- `fix/` — corrección de bug
- `refactor/` — refactoring sin cambio funcional
- `hotfix/` — corrección urgente de producción
- `chore/` — mantenimiento, actualizaciones de deps
- `docs/` — solo documentación

Ejemplos:
- `feat/modulo-facturacion-electronica`
- `fix/error-calculo-impuesto-ieps`
- `hotfix/sql-injection-endpoint-productos`
- `refactor/migrar-callbacks-a-promises`

Reglas:
- Nombre describe el trabajo, no la persona ni el ticket.
  - Mal: `branch-juan`, `feat-123`, `nueva-rama`
  - Bien: `feat/exportacion-reporte-pdf`
- Vida corta: las ramas de feature no duran más de 2 semanas sin mergearse.
  Ramas largas generan conflictos masivos.
- Eliminar la rama después del merge al branch base.

---

## No force-push a main / develop

- `git push --force` y `git push --force-with-lease` están prohibidos en
  `main`, `master` y `develop`.
- Estas ramas deben tener protección de branch habilitada en el repositorio.
- Si se requiere reescribir historial de main: escalar a decisión del equipo,
  con plan de comunicación y ventana de mantenimiento.
- En ramas de feature propias: `--force-with-lease` está permitido para rebase
  interactivo antes del PR, con precaución.
- Rebase en ramas compartidas (más de un colaborador): siempre coordinar antes.

---

## PRs — descripción y test plan obligatorios

Todo Pull Request debe incluir:

**Título**: sigue el mismo formato que el mensaje de commit.

**Descripción mínima**:
```markdown
## Resumen
- Qué cambió y por qué (1-3 bullets)

## Cambios principales
- Lista de los cambios técnicos relevantes

## Test plan
- [ ] Paso 1 para verificar manualmente
- [ ] Paso 2 para verificar el caso edge
- [ ] Caso de error verificado

## Screenshots (si hay cambios de UI)

## Notas para el reviewer
- Contexto adicional, decisiones tomadas, alternativas descartadas
```

Reglas adicionales:
- PRs de más de 500 líneas cambiadas: justificar o dividir en PRs menores.
- Asignar reviewer antes de solicitar revisión.
- No mergear el propio PR sin revisión (excepto hotfixes urgentes documentados).
- Resolver todos los comentarios antes de mergear (o marcar como `wontfix` con justificación).

---

## Squash antes de merge

- Commits WIP, de typos y de fix de review se squashean antes del merge.
- El historial de main muestra solo commits semánticos y atómicos.
- Estrategia recomendada: `Squash and merge` desde la UI de GitHub/GitLab,
  o `rebase interactivo` antes del merge.
- El mensaje del squash debe ser descriptivo del cambio completo, no solo
  el primer mensaje de la rama.
- Ramas con múltiples commits lógicos independientes: usar `rebase` en lugar
  de `squash` para preservar la granularidad.

---

## Flujo completo de trabajo

```
main ─────────────────────────────────────────► main
       │                              ▲
       └─ feat/nombre ──[commits]──[squash]─┘
              │
              └─ [PR] ──[review] ──[CI pass] ──[merge]
```

1. Crear branch desde `main` (o `develop` si existe).
2. Hacer commits atómicos en la branch.
3. Mantener la branch actualizada con `git rebase main` (no merge).
4. Abrir PR con descripción completa.
5. Pasar CI (linter, tests, type-check).
6. Obtener aprobación de al menos 1 reviewer.
7. Squash y merge.
8. Eliminar la branch.

---

## Reglas de emergencia (hotfixes)

- Un hotfix de producción puede saltarse el proceso completo de review si hay
  indisponibilidad activa, con las siguientes condiciones:
  - Notificar al equipo en el canal de incidencias antes de mergear.
  - El fix más pequeño posible — solo lo que resuelve el incidente.
  - PR de follow-up con tests dentro de 24 horas.
  - Post-mortem si el incidente duró más de 30 minutos.

---

## Sincronización de versiones antes de release

Cuando se modifican componentes del sistema SWL (agentes, skills, reglas, hooks,
comandos, schemas o manifiestos), la versión debe actualizarse en TODOS los
archivos que la declaran antes de hacer commit y publicar:

| Archivo | Campo | Ejemplo |
|---------|-------|---------|
| `package.json` | `"version"` | `"5.0.3"` |
| `plugin.json` | `"version"` | `"5.0.3"` |
| `SALUD.md` | `Versión del sistema` | `5.0.3` (todas las ocurrencias) |
| `.claude/.swl-install-state.json` | `"versionSistema"` | `"5.0.3"` (local, gitignored) |

El tipo de bump sigue SemVer:
- **PATCH** (5.0.X): correcciones de bugs, mejoras de redacción, ajustes de patrones
- **MINOR** (5.X.0): agente nuevo, skill nuevo, comando nuevo, regla nueva
- **MAJOR** (X.0.0): cambio breaking en schemas, reglas obligatorias nuevas, restructuración

Verificación rápida de consistencia:
```bash
node -e "const p=require('./package.json'),l=require('./plugin.json');console.log(p.version===l.version?'OK: '+p.version:'INCONSISTENTE: pkg='+p.version+' plugin='+l.version)"
```

---

## Checklist antes de abrir un PR

- [ ] Commits son atómicos y tienen mensajes descriptivos
- [ ] Branch actualizada con `rebase` desde main (sin conflictos)
- [ ] Tests pasan localmente
- [ ] Linter y type-checker pasan
- [ ] PR tiene descripción, cambios principales y test plan
- [ ] No se fuerza push a main
- [ ] Commits WIP squasheados
- [ ] Si se modificaron componentes del sistema (agentes, skills, reglas, hooks):
      versión actualizada en package.json, plugin.json y SALUD.md
