# Regla: Documentación

La documentación es para los humanos que vienen después — incluyendo tú mismo
en seis meses. Documenta el POR QUÉ, no el QUÉ: el código ya explica el qué.
La documentación explica el contexto, las restricciones y las decisiones.

---

## Documentar el POR QUÉ, no el QUÉ

El código bien escrito es autoexplicativo en el QUÉ. Los comentarios agregan
valor cuando explican lo que el código no puede expresar por sí solo:

- Por qué se tomó esta decisión en lugar de la alternativa obvia
- Por qué hay una excepción a la regla general
- Qué restricción externa (API, regulación, legacy) explica una solución poco intuitiva
- Qué bug histórico motivó este código aparentemente innecesario

Mal — documenta el qué (redundante con el código):
```python
# Incrementar el contador
contador += 1

# Verificar si el usuario está activo
if usuario.es_activo:
```

Bien — documenta el por qué:
```python
# El SAT requiere que el folio fiscal sea consecutivo sin gaps.
# Usar SEQUENCE de PostgreSQL garantiza atomicidad bajo concurrencia.
folio = await db.execute(text("SELECT nextval('folio_fiscal_seq')"))

# HACK: la API de CFDI devuelve 200 incluso para errores de validación.
# Detectar el error por la presencia del campo "faultcode" en la respuesta.
if "faultcode" in respuesta:
```

---

## README actualizado

El README es el punto de entrada al proyecto. Debe estar siempre actualizado.
Un README desactualizado es peor que no tener README — genera confianza falsa.

Estructura mínima del README del proyecto:
```markdown
# Nombre del Proyecto

Descripción en 2-3 líneas: qué hace, para quién, qué problema resuelve.

## Requisitos previos
- Python 3.12+
- PostgreSQL 15+
- Node.js 20+

## Instalación y setup local
Instrucciones paso a paso. Que funcionen. Probarlas en una máquina limpia.

## Cómo correr los tests

## Cómo levantar el entorno de desarrollo

## Variables de entorno requeridas
Lista con descripción de cada variable (nunca valores reales).

## Arquitectura
Link al diagrama o descripción de alto nivel.

## Contribuir
Link al CONTRIBUTING.md o instrucciones básicas.
```

Reglas del README:
- Las instrucciones de instalación deben funcionar. Probarlas periódicamente.
- Actualizar el README en el mismo PR que introduce el cambio que lo hace obsoleto.
- Sin secciones "TODO" o "próximamente" — si no está listo, no va en el README.
- Sin secciones genéricas copiadas de templates sin personalizar.

---

## CHANGELOG con formato Keep a Changelog

Formato oficial: https://keepachangelog.com/es/1.0.0/

Estructura:
```markdown
# Changelog

## [Sin publicar]

### Agregado
- Nueva funcionalidad X

## [1.2.0] - 2026-01-15

### Agregado
- Soporte para exportación de reportes en PDF

### Cambiado
- El endpoint /facturas ahora devuelve paginación por defecto

### Corregido
- Error al calcular IEPS para productos con tasa 0%

### Eliminado
- Endpoint /facturas/legacy deprecado desde v1.0

## [1.1.0] - 2025-11-20
...
```

Reglas del CHANGELOG:
- Actualizar en cada PR que cambia comportamiento observable por el usuario.
  Cambios internos de refactor o tests: no requieren entrada en CHANGELOG.
- Sección "Sin publicar" para cambios no lanzados todavía.
  Al lanzar: renombrar la sección con la versión y fecha.
- Una línea por cambio, redactada para el usuario, no para el desarrollador.
  "Corregido error al exportar PDF con caracteres especiales" > "fix: null pointer en PdfExportService"
- El CHANGELOG vive en la raíz del repositorio como `CHANGELOG.md`.

---

## ADRs para decisiones arquitecturales

Ver también: `reglas/arquitectura.md`

- Directorio: `docs/adr/` en el repositorio.
- Índice en `docs/adr/README.md` con lista de todos los ADRs y su estado.
- Buscar en los ADRs existentes antes de proponer una decisión nueva.
  Si ya hay un ADR que la cubre: referenciarlo, no crear uno duplicado.
- ADRs deprecados o reemplazados: no borrar — actualizar el estado y referenciar
  el ADR nuevo. El historial de decisiones es valioso.

---

## Runbooks para procesos operativos

Un runbook es una guía paso a paso para ejecutar un proceso operativo:
deploy, rollback, migración de datos, respuesta a incidentes.

Ubicación: `docs/runbooks/`

Estructura mínima de un runbook:
```markdown
# Runbook: [Nombre del proceso]

**Propósito**: Qué hace este proceso y cuándo ejecutarlo.
**Tiempo estimado**: N minutos
**Prerrequisitos**: Qué accesos/herramientas se necesitan
**Riesgos**: Qué puede salir mal y cómo mitigarlo

## Pasos

### 1. [Nombre del paso]
```bash
comando exacto a ejecutar
```
**Resultado esperado**: descripción de qué debe pasar.
**Si falla**: qué hacer.

## Verificación post-ejecución
- [ ] Paso de verificación 1
- [ ] Paso de verificación 2

## Rollback
Pasos para deshacer el proceso si algo falla.
```

Procesos que DEBEN tener runbook:
- Deploy a producción
- Rollback de deploy
- Migraciones de BD en producción
- Rotación de secrets
- Respuesta a incidente de seguridad
- Backup y restore de BD

---

## Documentación de APIs

- Toda API REST tiene documentación OpenAPI/Swagger generada automáticamente
  y disponible en `/docs` (desarrollo) y `/api/docs` (producción con auth).
- Cada endpoint tiene descripción, parámetros documentados y ejemplos de respuesta.
- Los campos de schemas Pydantic con `description=` son parte de la spec — no opcionales.
- Errores posibles documentados (qué regresa en 400, 401, 403, 404, 422, 500).

---

## Sin documentación vacía o genérica

Documentación que no ayuda es ruido que hay que mantener:

Señales de documentación vacía a eliminar:
- `"""Constructor de la clase Factura"""` — obvio del nombre.
- `"""Parámetros: id (int): el id"""` — sin información nueva.
- Secciones del README copiadas de un template sin personalizar.
- Comentarios `# TODO` sin número de ticket y fecha.
- ADRs con "Contexto: se necesitaba una solución" sin detalles reales.

Si no se tiene tiempo de documentar bien: es mejor no poner documentación vacía.
Marcar explícitamente con `# NODOC: pendiente de documentar (ticket #NNN)`.

---

## Docstrings — cuándo y cómo

Python:
- Docstring obligatorio en módulos, clases públicas y funciones públicas no triviales.
- Funciones privadas (`_nombre`) y triviales (getters simples): docstring opcional.
- Formato Google Style:
  ```python
  def calcular_iva(precio: Decimal, tasa: float) -> Decimal:
      """Calcula el IVA sobre el precio dado.

      No incluye IEPS ni retenciones. Para cálculo completo usar
      `calcular_impuestos_completos()`.

      Args:
          precio: Precio base sin impuestos.
          tasa: Tasa como decimal (0.16 para 16%).

      Returns:
          Monto del IVA redondeado a 2 decimales.

      Raises:
          ValueError: Si la tasa es negativa o mayor que 1.
      """
  ```

TypeScript:
- JSDoc en funciones públicas de services y utilities.
- Componentes Angular: comentario en el selector explicando el propósito del componente.

---

## Checklist de documentación antes de merge

- [ ] README refleja los cambios del PR
- [ ] CHANGELOG actualizado si hay cambio observable por el usuario
- [ ] ADR creado si hubo decisión arquitectural significativa
- [ ] Endpoints nuevos con descripción en el schema OpenAPI
- [ ] Sin comentarios que explican el qué (solo el por qué)
- [ ] Sin secciones TODO vacías sin ticket asociado
- [ ] Runbook creado si se agregó proceso operativo nuevo
