swl-ses 3.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/CLAUDE.md +425 -0
  2. package/_userland/agentes/.gitkeep +0 -0
  3. package/_userland/habilidades/.gitkeep +0 -0
  4. package/agentes/accesibilidad-wcag-swl.md +683 -0
  5. package/agentes/arquitecto-swl.md +210 -0
  6. package/agentes/auto-evolucion-swl.md +408 -0
  7. package/agentes/backend-api-swl.md +442 -0
  8. package/agentes/backend-node-swl.md +439 -0
  9. package/agentes/backend-python-swl.md +469 -0
  10. package/agentes/backend-workers-swl.md +444 -0
  11. package/agentes/cloud-infra-swl.md +466 -0
  12. package/agentes/consolidador-swl.md +487 -0
  13. package/agentes/datos-swl.md +568 -0
  14. package/agentes/depurador-swl.md +301 -0
  15. package/agentes/devops-ci-swl.md +352 -0
  16. package/agentes/disenador-ui-swl.md +546 -0
  17. package/agentes/documentador-swl.md +323 -0
  18. package/agentes/frontend-angular-swl.md +603 -0
  19. package/agentes/frontend-css-swl.md +700 -0
  20. package/agentes/frontend-react-swl.md +672 -0
  21. package/agentes/frontend-swl.md +483 -0
  22. package/agentes/frontend-tailwind-swl.md +808 -0
  23. package/agentes/implementador-swl.md +235 -0
  24. package/agentes/investigador-swl.md +274 -0
  25. package/agentes/investigador-ux-swl.md +482 -0
  26. package/agentes/migrador-swl.md +389 -0
  27. package/agentes/mobile-android-swl.md +473 -0
  28. package/agentes/mobile-cross-swl.md +501 -0
  29. package/agentes/mobile-ios-swl.md +464 -0
  30. package/agentes/notificador-swl.md +886 -0
  31. package/agentes/observabilidad-swl.md +408 -0
  32. package/agentes/orquestador-swl.md +490 -0
  33. package/agentes/planificador-swl.md +222 -0
  34. package/agentes/producto-prd-swl.md +565 -0
  35. package/agentes/release-manager-swl.md +545 -0
  36. package/agentes/rendimiento-swl.md +691 -0
  37. package/agentes/revisor-codigo-swl.md +254 -0
  38. package/agentes/revisor-seguridad-swl.md +316 -0
  39. package/agentes/tdd-qa-swl.md +323 -0
  40. package/agentes/ux-disenador-swl.md +498 -0
  41. package/bin/swl-ses.js +119 -0
  42. package/comandos/swl/actualizar.md +117 -0
  43. package/comandos/swl/aprender.md +348 -0
  44. package/comandos/swl/auditar-deps.md +390 -0
  45. package/comandos/swl/autoresearch.md +346 -0
  46. package/comandos/swl/checkpoint.md +296 -0
  47. package/comandos/swl/compactar.md +283 -0
  48. package/comandos/swl/crear-skill.md +609 -0
  49. package/comandos/swl/discutir-fase.md +230 -0
  50. package/comandos/swl/ejecutar-fase.md +302 -0
  51. package/comandos/swl/evolucionar.md +377 -0
  52. package/comandos/swl/instalar.md +220 -0
  53. package/comandos/swl/mapear-codebase.md +205 -0
  54. package/comandos/swl/nuevo-proyecto.md +154 -0
  55. package/comandos/swl/planear-fase.md +221 -0
  56. package/comandos/swl/release.md +405 -0
  57. package/comandos/swl/salud.md +382 -0
  58. package/comandos/swl/verificar.md +292 -0
  59. package/habilidades/accesibilidad-a11y/SKILL.md +584 -0
  60. package/habilidades/angular-avanzado/SKILL.md +491 -0
  61. package/habilidades/angular-moderno/SKILL.md +326 -0
  62. package/habilidades/api-rest-diseno/SKILL.md +302 -0
  63. package/habilidades/api-rest-diseno/recursos/openapi-template.yaml +506 -0
  64. package/habilidades/aprendizaje-continuo/SKILL.md +369 -0
  65. package/habilidades/async-python/SKILL.md +474 -0
  66. package/habilidades/auth-patrones/SKILL.md +488 -0
  67. package/habilidades/auto-evolucion-protocolo/SKILL.md +376 -0
  68. package/habilidades/autoresearch/SKILL.md +248 -0
  69. package/habilidades/autoresearch/recursos/checklist-template.md +191 -0
  70. package/habilidades/autoresearch/scripts/calcular-score.js +88 -0
  71. package/habilidades/checklist-calidad/SKILL.md +247 -0
  72. package/habilidades/checklist-calidad/recursos/quality-report-template.md +148 -0
  73. package/habilidades/checklist-seguridad/SKILL.md +224 -0
  74. package/habilidades/checkpoints-verificacion/SKILL.md +309 -0
  75. package/habilidades/checkpoints-verificacion/recursos/checkpoint-templates.md +360 -0
  76. package/habilidades/ci-cd-pipelines/SKILL.md +583 -0
  77. package/habilidades/ci-cd-pipelines/recursos/github-actions-template.yaml +403 -0
  78. package/habilidades/cloud-aws/SKILL.md +497 -0
  79. package/habilidades/compactacion-contexto/SKILL.md +201 -0
  80. package/habilidades/contenedores-docker/SKILL.md +453 -0
  81. package/habilidades/contenedores-docker/recursos/dockerfile-template.dockerfile +160 -0
  82. package/habilidades/css-moderno/SKILL.md +463 -0
  83. package/habilidades/datos-etl/SKILL.md +486 -0
  84. package/habilidades/dependencias-auditoria/SKILL.md +293 -0
  85. package/habilidades/deprecacion-migracion/SKILL.md +485 -0
  86. package/habilidades/design-tokens/SKILL.md +519 -0
  87. package/habilidades/discutir-fase/SKILL.md +167 -0
  88. package/habilidades/diseno-responsivo/SKILL.md +326 -0
  89. package/habilidades/django-experto/SKILL.md +395 -0
  90. package/habilidades/doc-sync/SKILL.md +259 -0
  91. package/habilidades/ejecutar-fase/SKILL.md +199 -0
  92. package/habilidades/estructura-proyecto-claude/SKILL.md +459 -0
  93. package/habilidades/estructura-proyecto-claude/recursos/claude-md-template.md +261 -0
  94. package/habilidades/estructura-proyecto-claude/recursos/frontmatter-y-hooks-referencia.md +213 -0
  95. package/habilidades/estructura-proyecto-claude/recursos/mcp-json-template.json +77 -0
  96. package/habilidades/estructura-proyecto-claude/recursos/variantes-por-stack.md +177 -0
  97. package/habilidades/event-driven/SKILL.md +580 -0
  98. package/habilidades/extractor-de-aprendizajes/SKILL.md +234 -0
  99. package/habilidades/fastapi-experto/SKILL.md +368 -0
  100. package/habilidades/frontend-avanzado/SKILL.md +555 -0
  101. package/habilidades/git-worktrees-paralelo/SKILL.md +246 -0
  102. package/habilidades/iam-secretos/SKILL.md +511 -0
  103. package/habilidades/instalar-sistema/SKILL.md +140 -0
  104. package/habilidades/kubernetes-orquestacion/SKILL.md +549 -0
  105. package/habilidades/manejo-errores/SKILL.md +512 -0
  106. package/habilidades/mapear-codebase/SKILL.md +199 -0
  107. package/habilidades/microservicios/SKILL.md +473 -0
  108. package/habilidades/mobile-flutter/SKILL.md +566 -0
  109. package/habilidades/mobile-react-native/SKILL.md +493 -0
  110. package/habilidades/monitoring-alertas/SKILL.md +447 -0
  111. package/habilidades/node-experto/SKILL.md +521 -0
  112. package/habilidades/notificaciones-multicanal/SKILL.md +448 -0
  113. package/habilidades/notificaciones-multicanal/recursos/config-template.json +115 -0
  114. package/habilidades/nuevo-proyecto/SKILL.md +183 -0
  115. package/habilidades/patrones-python/SKILL.md +381 -0
  116. package/habilidades/performance-baseline/SKILL.md +243 -0
  117. package/habilidades/planear-fase/SKILL.md +184 -0
  118. package/habilidades/postgresql-experto/SKILL.md +379 -0
  119. package/habilidades/react-experto/SKILL.md +434 -0
  120. package/habilidades/react-optimizacion/SKILL.md +328 -0
  121. package/habilidades/release-semver/SKILL.md +226 -0
  122. package/habilidades/release-semver/scripts/generar-changelog.sh +238 -0
  123. package/habilidades/sql-optimizacion/SKILL.md +314 -0
  124. package/habilidades/tailwind-experto/SKILL.md +412 -0
  125. package/habilidades/tdd-workflow/SKILL.md +267 -0
  126. package/habilidades/testing-python/SKILL.md +350 -0
  127. package/habilidades/threat-model-lite/SKILL.md +218 -0
  128. package/habilidades/typescript-avanzado/SKILL.md +454 -0
  129. package/habilidades/ux-diseno/SKILL.md +488 -0
  130. package/habilidades/validacion-ci-sistema/SKILL.md +543 -0
  131. package/habilidades/validacion-ci-sistema/scripts/validar-sistema.sh +286 -0
  132. package/habilidades/verificar-trabajo/SKILL.md +208 -0
  133. package/habilidades/wireframes-flujos/SKILL.md +396 -0
  134. package/habilidades/workflow-claude-code/SKILL.md +359 -0
  135. package/hooks/calidad-pre-commit.js +578 -0
  136. package/hooks/escaneo-secretos.js +302 -0
  137. package/hooks/extraccion-aprendizajes.js +550 -0
  138. package/hooks/linea-estado.js +249 -0
  139. package/hooks/monitor-contexto.js +230 -0
  140. package/hooks/proteccion-rutas.js +249 -0
  141. package/manifiestos/hooks-config.json +41 -0
  142. package/manifiestos/modulos.json +318 -0
  143. package/manifiestos/perfiles.json +189 -0
  144. package/package.json +45 -0
  145. package/plantillas/PROJECT.md +122 -0
  146. package/plantillas/REQUIREMENTS.md +132 -0
  147. package/plantillas/ROADMAP.md +143 -0
  148. package/plantillas/STATE.md +109 -0
  149. package/plantillas/research/ARCHITECTURE.md +220 -0
  150. package/plantillas/research/FEATURES.md +175 -0
  151. package/plantillas/research/PITFALLS.md +299 -0
  152. package/plantillas/research/STACK.md +233 -0
  153. package/plantillas/research/SUMMARY.md +165 -0
  154. package/plugin.json +144 -0
  155. package/reglas/accesibilidad.md +269 -0
  156. package/reglas/api-diseno.md +400 -0
  157. package/reglas/arquitectura.md +183 -0
  158. package/reglas/cloud-infra.md +247 -0
  159. package/reglas/docs.md +245 -0
  160. package/reglas/estilo-codigo.md +179 -0
  161. package/reglas/git-workflow.md +186 -0
  162. package/reglas/performance.md +195 -0
  163. package/reglas/pruebas.md +159 -0
  164. package/reglas/seguridad.md +151 -0
  165. package/reglas/skills-estandar.md +473 -0
  166. package/scripts/actualizar.js +51 -0
  167. package/scripts/desinstalar.js +86 -0
  168. package/scripts/doctor.js +222 -0
  169. package/scripts/inicializar.js +89 -0
  170. package/scripts/instalador.js +333 -0
  171. package/scripts/lib/detectar-runtime.js +177 -0
  172. package/scripts/lib/estado.js +112 -0
  173. package/scripts/lib/hooks-settings.js +283 -0
  174. package/scripts/lib/manifiestos.js +138 -0
  175. package/scripts/lib/seguridad.js +160 -0
  176. package/scripts/publicar.js +209 -0
  177. package/scripts/validar.js +120 -0
@@ -0,0 +1,328 @@
1
+ ---
2
+ name: react-optimizacion
3
+ description: Optimización de rendimiento en React. memo, useMemo, useCallback, code splitting, lazy loading, concurrent features, Suspense y patrones de estado eficiente.
4
+ ---
5
+
6
+ # Optimización de Rendimiento en React
7
+
8
+ ## Principio de optimización prematura
9
+
10
+ **No optimices antes de medir.** La mayoría de los problemas de rendimiento en React
11
+ provienen de re-renders innecesarios o de carga inicial pesada. Primero identifica
12
+ el cuello de botella con React DevTools Profiler, luego aplica la solución correcta.
13
+
14
+ ---
15
+
16
+ ## Re-renders: cuándo ocurren y cómo controlarlos
17
+
18
+ Un componente se re-renderiza cuando:
19
+ 1. Su propio estado cambia (`useState`, `useReducer`).
20
+ 2. Su componente padre se re-renderiza (incluso si las props no cambiaron).
21
+ 3. Un contexto del que consume cambia.
22
+
23
+ ### React.memo — evitar re-renders por props iguales
24
+
25
+ ```tsx
26
+ import React, { memo } from 'react';
27
+
28
+ // Memorizar componente que recibe props estables
29
+ const FacturaCard = memo(function FacturaCard({
30
+ factura,
31
+ onCancelar,
32
+ }: {
33
+ factura: Factura;
34
+ onCancelar: (id: string) => void;
35
+ }) {
36
+ return (
37
+ <div className="border rounded-lg p-4">
38
+ <h3 className="font-semibold">{factura.folio}</h3>
39
+ <p>{factura.cliente}</p>
40
+ <button onClick={() => onCancelar(factura.id)}>Cancelar</button>
41
+ </div>
42
+ );
43
+ });
44
+
45
+ // Comparación personalizada cuando la comparación shallow no es suficiente
46
+ const FacturaTable = memo(
47
+ function FacturaTable({ facturas }: { facturas: Factura[] }) {
48
+ return <table>...</table>;
49
+ },
50
+ (prev, next) => {
51
+ // true = NO re-renderizar
52
+ return prev.facturas.length === next.facturas.length &&
53
+ prev.facturas.every((f, i) => f.id === next.facturas[i].id);
54
+ }
55
+ );
56
+ ```
57
+
58
+ ### useMemo — memorizar cálculos costosos
59
+
60
+ ```tsx
61
+ import { useMemo } from 'react';
62
+
63
+ function ResumenFacturas({ facturas }: { facturas: Factura[] }) {
64
+ // Solo recalcular cuando facturas cambia
65
+ const estadisticas = useMemo(() => ({
66
+ total: facturas.reduce((sum, f) => sum + f.monto, 0),
67
+ emitidas: facturas.filter(f => f.estatus === 'emitida').length,
68
+ canceladas: facturas.filter(f => f.estatus === 'cancelada').length,
69
+ promedio: facturas.length > 0
70
+ ? facturas.reduce((sum, f) => sum + f.monto, 0) / facturas.length
71
+ : 0,
72
+ }), [facturas]);
73
+
74
+ // MAL: calcular en el render sin useMemo (se recalcula en CADA re-render del padre)
75
+ // const total = facturas.reduce((sum, f) => sum + f.monto, 0);
76
+
77
+ return (
78
+ <div>
79
+ <p>Total: ${estadisticas.total}</p>
80
+ <p>Emitidas: {estadisticas.emitidas}</p>
81
+ </div>
82
+ );
83
+ }
84
+ ```
85
+
86
+ ### useCallback — estabilizar referencias de funciones
87
+
88
+ ```tsx
89
+ import { useCallback } from 'react';
90
+
91
+ function ListaFacturas() {
92
+ const [facturas, setFacturas] = useState<Factura[]>([]);
93
+
94
+ // Sin useCallback, esta función tiene nueva referencia en cada render
95
+ // lo que causa que FacturaCard (con memo) se re-renderice de todas formas
96
+ const handleCancelar = useCallback((id: string) => {
97
+ setFacturas(prev => prev.map(f =>
98
+ f.id === id ? { ...f, estatus: 'cancelada' } : f
99
+ ));
100
+ }, []); // Sin dependencias porque usa el setter funcional de useState
101
+
102
+ const handleActualizar = useCallback((id: string, datos: Partial<Factura>) => {
103
+ setFacturas(prev => prev.map(f =>
104
+ f.id === id ? { ...f, ...datos } : f
105
+ ));
106
+ }, []);
107
+
108
+ return (
109
+ <div>
110
+ {facturas.map(factura => (
111
+ <FacturaCard
112
+ key={factura.id}
113
+ factura={factura}
114
+ onCancelar={handleCancelar} // Referencia estable → memo funciona
115
+ />
116
+ ))}
117
+ </div>
118
+ );
119
+ }
120
+ ```
121
+
122
+ ---
123
+
124
+ ## Code Splitting y Lazy Loading
125
+
126
+ ### React.lazy + Suspense
127
+
128
+ ```tsx
129
+ import React, { lazy, Suspense } from 'react';
130
+ import { Routes, Route } from 'react-router-dom';
131
+
132
+ // Lazy imports — cada módulo se convierte en un chunk separado
133
+ const FacturasPage = lazy(() => import('./pages/FacturasPage'));
134
+ const ReportesPage = lazy(() => import('./pages/ReportesPage'));
135
+ const ConfiguracionPage = lazy(() => import('./pages/ConfiguracionPage'));
136
+
137
+ function App() {
138
+ return (
139
+ <Suspense fallback={<PageLoader />}>
140
+ <Routes>
141
+ <Route path="/facturas" element={<FacturasPage />} />
142
+ <Route path="/reportes" element={<ReportesPage />} />
143
+ <Route path="/configuracion" element={<ConfiguracionPage />} />
144
+ </Routes>
145
+ </Suspense>
146
+ );
147
+ }
148
+ ```
149
+
150
+ ### Lazy loading de componentes pesados
151
+
152
+ ```tsx
153
+ import { lazy, Suspense, useState } from 'react';
154
+
155
+ // Cargar gráfica solo cuando el usuario la solicita
156
+ const GraficaVentas = lazy(() => import('./GraficaVentas'));
157
+
158
+ function Dashboard() {
159
+ const [mostrarGrafica, setMostrarGrafica] = useState(false);
160
+
161
+ return (
162
+ <div>
163
+ <button onClick={() => setMostrarGrafica(true)}>
164
+ Ver gráfica de ventas
165
+ </button>
166
+ {mostrarGrafica && (
167
+ <Suspense fallback={<div className="h-64 animate-pulse bg-gray-100" />}>
168
+ <GraficaVentas />
169
+ </Suspense>
170
+ )}
171
+ </div>
172
+ );
173
+ }
174
+ ```
175
+
176
+ ---
177
+
178
+ ## Concurrent Features
179
+
180
+ ### useTransition — marcar actualizaciones como no urgentes
181
+
182
+ ```tsx
183
+ import { useTransition, useState } from 'react';
184
+
185
+ function BuscadorFacturas() {
186
+ const [query, setQuery] = useState('');
187
+ const [resultados, setResultados] = useState<Factura[]>([]);
188
+ const [isPending, startTransition] = useTransition();
189
+
190
+ const handleBusqueda = (valor: string) => {
191
+ // Actualización urgente: el input responde inmediatamente
192
+ setQuery(valor);
193
+
194
+ // Actualización no urgente: los resultados pueden esperar
195
+ startTransition(() => {
196
+ const filtrados = buscarFacturas(valor);
197
+ setResultados(filtrados);
198
+ });
199
+ };
200
+
201
+ return (
202
+ <div>
203
+ <input
204
+ value={query}
205
+ onChange={e => handleBusqueda(e.target.value)}
206
+ placeholder="Buscar facturas..."
207
+ />
208
+ {isPending && <span className="text-gray-400">Buscando...</span>}
209
+ <ListaResultados resultados={resultados} />
210
+ </div>
211
+ );
212
+ }
213
+ ```
214
+
215
+ ### useDeferredValue — versión diferida de un valor
216
+
217
+ ```tsx
218
+ import { useDeferredValue, memo } from 'react';
219
+
220
+ function ListaFiltrada({ items }: { items: string[] }) {
221
+ const [filtro, setFiltro] = useState('');
222
+ // Versión diferida del filtro — permite que el input sea fluido
223
+ const filtroDeferred = useDeferredValue(filtro);
224
+
225
+ // isStale detecta si estamos mostrando resultado desactualizado
226
+ const isStale = filtro !== filtroDeferred;
227
+
228
+ const itemsFiltrados = useMemo(
229
+ () => items.filter(item => item.includes(filtroDeferred)),
230
+ [items, filtroDeferred]
231
+ );
232
+
233
+ return (
234
+ <div>
235
+ <input value={filtro} onChange={e => setFiltro(e.target.value)} />
236
+ <ul style={{ opacity: isStale ? 0.6 : 1 }}>
237
+ {itemsFiltrados.map(item => <li key={item}>{item}</li>)}
238
+ </ul>
239
+ </div>
240
+ );
241
+ }
242
+ ```
243
+
244
+ ---
245
+
246
+ ## Virtualización para listas largas
247
+
248
+ ```tsx
249
+ import { useVirtualizer } from '@tanstack/react-virtual';
250
+ import { useRef } from 'react';
251
+
252
+ function ListaVirtualizada({ facturas }: { facturas: Factura[] }) {
253
+ const contenedorRef = useRef<HTMLDivElement>(null);
254
+
255
+ const virtualizer = useVirtualizer({
256
+ count: facturas.length,
257
+ getScrollElement: () => contenedorRef.current,
258
+ estimateSize: () => 80, // altura estimada en px por fila
259
+ overscan: 5, // filas extra fuera del viewport
260
+ });
261
+
262
+ return (
263
+ <div ref={contenedorRef} style={{ height: '600px', overflow: 'auto' }}>
264
+ <div style={{ height: `${virtualizer.getTotalSize()}px`, position: 'relative' }}>
265
+ {virtualizer.getVirtualItems().map(virtualItem => (
266
+ <div
267
+ key={virtualItem.key}
268
+ style={{
269
+ position: 'absolute',
270
+ top: 0,
271
+ left: 0,
272
+ width: '100%',
273
+ transform: `translateY(${virtualItem.start}px)`,
274
+ }}
275
+ >
276
+ <FacturaCard factura={facturas[virtualItem.index]} />
277
+ </div>
278
+ ))}
279
+ </div>
280
+ </div>
281
+ );
282
+ }
283
+ ```
284
+
285
+ ---
286
+
287
+ ## Optimización de Context
288
+
289
+ El contexto causa re-render en TODOS los consumidores cuando cambia.
290
+ Dividir en contextos más pequeños o usar selectores:
291
+
292
+ ```tsx
293
+ // MAL: un solo contexto con todo el estado
294
+ const AppContext = createContext<AppState>({...});
295
+
296
+ // BIEN: separar por dominio y frecuencia de cambio
297
+ const AuthContext = createContext<AuthState>({...}); // Cambia raramente
298
+ const UIContext = createContext<UIState>({...}); // Cambia frecuentemente
299
+ const FacturasContext = createContext<FacturasState>({...}); // Cambia al interactuar
300
+
301
+ // BIEN: con useMemo para estabilizar el valor del contexto
302
+ function AuthProvider({ children }: { children: React.ReactNode }) {
303
+ const [usuario, setUsuario] = useState<Usuario | null>(null);
304
+
305
+ const value = useMemo(() => ({
306
+ usuario,
307
+ login: async (creds: Credentials) => { ... },
308
+ logout: () => setUsuario(null),
309
+ }), [usuario]); // Solo se crea objeto nuevo cuando usuario cambia
310
+
311
+ return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
312
+ }
313
+ ```
314
+
315
+ ---
316
+
317
+ ## Cuándo NO usar memo/useMemo/useCallback
318
+
319
+ Estas optimizaciones tienen un costo: complejidad de código y overhead de comparación.
320
+ No aplicar cuando:
321
+
322
+ - El componente es simple y rápido de renderizar.
323
+ - Las props cambian en casi todos los re-renders de todas formas.
324
+ - El cálculo en `useMemo` es trivial (suma de 3 números).
325
+ - No hay evidencia medida de problema de rendimiento.
326
+
327
+ **Regla práctica**: medir primero con React DevTools Profiler. Si un componente
328
+ aparece en llamas largas o con muchos re-renders no esperados, entonces optimizar.
@@ -0,0 +1,226 @@
1
+ ---
2
+ name: release-semver
3
+ description: Versionado semántico (SemVer). Cuándo bumpar major/minor/patch, changelogs convencionales, estrategia de tags y proceso de release completo.
4
+ ---
5
+
6
+ # Versionado Semántico (SemVer)
7
+
8
+ ## Principio fundamental
9
+
10
+ Un número de versión tiene la forma `MAJOR.MINOR.PATCH` (ej. `2.4.1`). Cada segmento comunica
11
+ intención de compatibilidad a los consumidores del paquete o servicio.
12
+
13
+ ---
14
+
15
+ ## Cuándo bumpar cada segmento
16
+
17
+ ### PATCH — arreglos compatibles hacia atrás
18
+
19
+ Incrementa PATCH cuando:
20
+ - Se corrige un bug sin cambiar la interfaz pública.
21
+ - Se corrige documentación o typos en código que afectan comportamiento.
22
+ - Se mejoran mensajes de error sin cambiar el tipo de excepción.
23
+ - Se actualizan dependencias de parche (`requests 2.31.0 → 2.31.1`).
24
+
25
+ ```
26
+ 1.4.2 → 1.4.3 # fix: corrige cálculo incorrecto en factura
27
+ ```
28
+
29
+ ### MINOR — funcionalidad nueva compatible hacia atrás
30
+
31
+ Incrementa MINOR cuando:
32
+ - Se agrega un endpoint, método o parámetro opcional nuevo.
33
+ - Se agrega una funcionalidad que los consumidores pueden ignorar.
34
+ - Se depreca algo (pero aún funciona).
35
+ - Se actualiza una dependencia minor que agrega capacidades.
36
+
37
+ ```
38
+ 1.4.3 → 1.5.0 # feat: agrega exportación a PDF
39
+ ```
40
+
41
+ Al subir MINOR, el PATCH siempre regresa a 0.
42
+
43
+ ### MAJOR — cambios incompatibles hacia atrás (breaking changes)
44
+
45
+ Incrementa MAJOR cuando:
46
+ - Se elimina un endpoint, método o campo.
47
+ - Se cambia el tipo o contrato de un parámetro existente.
48
+ - Se cambia el comportamiento esperado de forma que rompe integraciones existentes.
49
+ - Se cambia la autenticación/autorización de forma incompatible.
50
+
51
+ ```
52
+ 1.5.0 → 2.0.0 # feat!: migra autenticación de JWT a OAuth2
53
+ ```
54
+
55
+ Al subir MAJOR, MINOR y PATCH regresan a 0.
56
+
57
+ ### Versión 0.x.y — desarrollo inicial
58
+
59
+ Mientras la versión MAJOR sea `0`, la API se considera inestable. Cualquier MINOR puede
60
+ contener breaking changes. Cuando el software está listo para producción, se lanza `1.0.0`.
61
+
62
+ ---
63
+
64
+ ## Commits Convencionales
65
+
66
+ Los commits convencionales generan el changelog automáticamente y determinan el bump.
67
+
68
+ ### Formato
69
+
70
+ ```
71
+ <tipo>[scope opcional][! para breaking]: <descripción corta>
72
+
73
+ [cuerpo opcional]
74
+
75
+ [footer opcional: BREAKING CHANGE: descripción]
76
+ ```
77
+
78
+ ### Tipos y su impacto en versión
79
+
80
+ | Tipo | Impacto versión | Descripción |
81
+ |------------|----------------|--------------------------------------------------|
82
+ | `fix` | PATCH | Corrección de bug |
83
+ | `feat` | MINOR | Nueva funcionalidad |
84
+ | `feat!` | MAJOR | Nueva funcionalidad con breaking change |
85
+ | `fix!` | MAJOR | Fix con breaking change |
86
+ | `refactor` | ninguno | Refactorización sin cambio de comportamiento |
87
+ | `chore` | ninguno | Tareas de mantenimiento (CI, deps, config) |
88
+ | `docs` | ninguno | Documentación únicamente |
89
+ | `test` | ninguno | Agregar o corregir tests |
90
+ | `perf` | PATCH | Mejora de rendimiento sin cambio de interfaz |
91
+ | `ci` | ninguno | Cambios en pipelines de CI/CD |
92
+ | `style` | ninguno | Formato, espacios, punto y coma (sin lógica) |
93
+
94
+ ### Ejemplos de commits bien escritos
95
+
96
+ ```bash
97
+ git commit -m "fix(auth): corrige expiración incorrecta de tokens de refresco"
98
+ git commit -m "feat(reportes): agrega exportación a Excel con formato condicional"
99
+ git commit -m "feat(api)!: cambia paginación de offset a cursor
100
+
101
+ BREAKING CHANGE: el parámetro 'page' fue reemplazado por 'cursor'.
102
+ Los clientes deben actualizar sus integraciones."
103
+ ```
104
+
105
+ ---
106
+
107
+ ## Proceso de release
108
+
109
+ ### Paso 1 — Preparar la rama de release
110
+
111
+ ```bash
112
+ # En main, crear rama release
113
+ git checkout -b release/2.1.0
114
+
115
+ # Actualizar versión en archivos del proyecto
116
+ # Python: pyproject.toml, __version__
117
+ # Node: package.json
118
+ # Java: pom.xml o build.gradle
119
+ ```
120
+
121
+ ### Paso 2 — Generar CHANGELOG
122
+
123
+ Usar `conventional-changelog` o `git-cliff` para generar el changelog automáticamente:
124
+
125
+ ```bash
126
+ # Con git-cliff (recomendado)
127
+ git cliff --tag v2.1.0 --output CHANGELOG.md
128
+
129
+ # Con conventional-changelog
130
+ npx conventional-changelog -p conventionalcommits -i CHANGELOG.md -s
131
+ ```
132
+
133
+ Estructura esperada del CHANGELOG:
134
+
135
+ ```markdown
136
+ ## [2.1.0] - 2026-03-25
137
+
138
+ ### Nuevas funcionalidades
139
+ - feat(reportes): agrega exportación a Excel (#234)
140
+ - feat(usuarios): agrega campo de foto de perfil (#241)
141
+
142
+ ### Correcciones
143
+ - fix(auth): corrige expiración incorrecta de tokens (#238)
144
+ - fix(factura): redondeo incorrecto en descuentos (#240)
145
+ ```
146
+
147
+ ### Paso 3 — Commit de versión y tag
148
+
149
+ ```bash
150
+ # Commit del bump de versión
151
+ git add pyproject.toml CHANGELOG.md
152
+ git commit -m "chore(release): v2.1.0"
153
+
154
+ # Crear tag anotado (no ligero)
155
+ git tag -a v2.1.0 -m "Release v2.1.0"
156
+
157
+ # Subir rama y tag
158
+ git push origin release/2.1.0
159
+ git push origin v2.1.0
160
+ ```
161
+
162
+ ### Paso 4 — Merge a main y develop
163
+
164
+ ```bash
165
+ git checkout main
166
+ git merge --no-ff release/2.1.0
167
+ git push origin main
168
+
169
+ git checkout develop
170
+ git merge --no-ff release/2.1.0
171
+ git push origin develop
172
+
173
+ git branch -d release/2.1.0
174
+ ```
175
+
176
+ ---
177
+
178
+ ## Estrategia de tags
179
+
180
+ ### Tags anotados vs. ligeros
181
+
182
+ Siempre usar **tags anotados** (`git tag -a`) para releases. Los tags ligeros son solo para
183
+ marcado temporal interno. Los tags anotados incluyen autor, fecha y mensaje — esto es esencial
184
+ para `git describe` y herramientas de release.
185
+
186
+ ### Convención de nombres
187
+
188
+ ```
189
+ v{MAJOR}.{MINOR}.{PATCH} # release estable: v2.1.0
190
+ v{MAJOR}.{MINOR}.{PATCH}-rc.{N} # release candidate: v2.1.0-rc.1
191
+ v{MAJOR}.{MINOR}.{PATCH}-beta.{N} # beta pública: v2.1.0-beta.2
192
+ v{MAJOR}.{MINOR}.{PATCH}-alpha.{N} # alpha interna: v2.1.0-alpha.1
193
+ ```
194
+
195
+ ### Listar y filtrar tags
196
+
197
+ ```bash
198
+ git tag --sort=-v:refname # Lista tags en orden semver descendente
199
+ git tag -l "v2.*" # Solo tags de la serie 2.x
200
+ git describe --tags --abbrev=0 # Último tag del commit actual
201
+ ```
202
+
203
+ ---
204
+
205
+ ## Herramientas recomendadas
206
+
207
+ | Herramienta | Uso |
208
+ |------------------------|----------------------------------------------|
209
+ | `git-cliff` | Generación de CHANGELOG desde commits |
210
+ | `commitizen` | Wizard interactivo para commits convencionales |
211
+ | `semantic-release` | Release automatizado desde CI |
212
+ | `bump2version` | Bump de versión en archivos Python |
213
+ | `conventional-commits` | Spec oficial de commits convencionales |
214
+
215
+ ---
216
+
217
+ ## Anti-patrones a evitar
218
+
219
+ - **Nunca reutilizar un tag**: Si el release `v2.1.0` se publicó, no se puede mover ese tag.
220
+ Si hay un error, publicar `v2.1.1`.
221
+ - **Nunca usar tags ligeros en releases**: No aportan metadata y dificultan trazabilidad.
222
+ - **Nunca saltarse MAJOR por miedo**: Si hay breaking change, es MAJOR. Ocultarlo como MINOR
223
+ rompe la confianza de los consumidores.
224
+ - **No mezclar tipos de commit en uno solo**: Un commit = un cambio lógico = un tipo.
225
+ - **No escribir changelogs manuales sin estructura**: Usar el formato estándar para que las
226
+ herramientas puedan procesarlos.