Ir al contenido
learn

Las ráfagas no son tasas: llegadas de eventos en el registro de disparadores

Departamento de Psicohistoria | Intermedio | 40 minutos | Traducción al español del borrador en inglés; revisión de fondo y prueba con aprendices pendientes

En este módulo convertirá un registro de eventos en recuentos por día de calendario, los comparará con lo que produciría una tasa constante, medirá la diferencia con el índice de dispersión y sustituirá una media engañosa por cifras que un plan pueda usar. Pregunta de proyecto: el registro de disparadores archivado contiene 594 eventos repartidos en 119 días de calendario, 100 de ellos activos. ¿Es una media de «unos cinco eventos al día» una descripción útil para planificar?

PSY-002 interpreta que la tasa de señales de conciencia se duplique a lo largo de tres ciclos como indicio de que una transición está cerca (es su quinta señal). Una tasa es una media; este módulo se pregunta qué dice una media sobre un registro cuyos eventos llegan en ráfagas. PSY-009 mide la concentración del mismo registro, PSY-022 compara sobre él modelos de recuento y PSY-024 se pregunta quién envió los eventos.

1. Contar por día de calendario, días vacíos incluidos

Sección titulada «1. Contar por día de calendario, días vacíos incluidos»

Observado. Hasta su retirada el 2026-07-18, el flujo de trabajo demerzel-driver-triggers.yml escribía un archivo JSON, un disparador (trigger), por cada push a la rama principal, cada incidencia (issue) abierta o reabierta, cada discusión creada y cada ejecución fallida de otros cuatro flujos de trabajo. state/triggers/archived/ contiene 594 de ellos, con marcas de tiempo del 2026-03-20 al 2026-07-16 y de solo tres tipos: 252 discussion_created, 207 push y 135 issue_opened. extract.py lee los 594 en el commit 4b03838, rechaza una carpeta que no coincida con su huella criptográfica fijada y escribe una fila por evento en observed-input.json. Los pocos archivos de disparadores que están fuera de la carpeta de archivados quedan excluidos.

Un día es la fecha UTC de la marca de tiempo de un disparador. Del primer día al último hay 119 días de calendario: 100 días activos, con al menos un evento, y 19 vacíos. Una tasa cuenta eventos por tiempo transcurrido, así que los días vacíos se quedan en la serie.

media por día de calendario = 594 / 119 = 4.99
media por día activo = 594 / 100 = 5.94

Calculado por analyze.py, con resultados en results.json:

Eventos en el día Días Eventos
0 19 0
1 a 2 76 89
3 a 11 13 72
12 o más 11 433

El tipo de día más frecuente es el de exactamente 1 evento: 63 días, el 52.94%. Hubo exactamente 5 eventos en 2 días, y 4, 5 o 6 eventos en 4 días, el 3.36% de los días. «Unos cinco al día» no describe casi ningún día.

Calcule las dos medias. Un colega presupuesta los próximos 30 días de calendario multiplicando por 30 la media por día activo. ¿Qué obtiene, qué da la media por día de calendario y qué ha fallado?

Respuesta: 594 / 119 = 4.99 y 594 / 100 = 5.94. Con la media por día de calendario, 30 × 594 / 119 = 149.75 eventos; con la media por día activo, 30 × 5.94 = 178.2, es decir, 119 / 100 = 1.19 veces la primera cifra: la media por día activo quita del denominador los 19 días vacíos, pero los próximos 30 días también tendrán días vacíos.

2. La referencia de Poisson y el índice de dispersión

Sección titulada «2. La referencia de Poisson y el índice de dispersión»

Si los eventos llegan de forma independiente entre sí y a una tasa constante (un proceso de Poisson), el recuento de un día sigue una distribución de Poisson, cuya varianza es igual a su media. El índice de dispersión D compara ambas:

probabilidad de Poisson P(k eventos) = media^k × exp(−media) / k!
varianza muestral s² = (Σx² − (Σx)² / n) / (n − 1)
índice de dispersión D = s² / media

Este módulo usa siempre la varianza muestral, con divisor n − 1. Un D cercano a 1 es lo que da una tasa constante; un D inferior a 1 indica recuentos más regulares que el azar (un reloj diario da 0); un D superior a 1 es sobredispersión: tramos tranquilos y ráfagas. Bajo un proceso de Poisson, (n − 1) × D sigue aproximadamente una distribución chi cuadrado con n − 1 grados de libertad, de modo que D tiene una desviación estándar de alrededor de sqrt(2 / (n − 1)), aquí 0.13 (Cox y Lewis 1966).

Calculado. Los recuentos diarios dan s² = 198.52 y D = 39.77, unas 298 de esas desviaciones estándar por encima de 1. La referencia es la distribución de Poisson con la media observada, 594/119:

Tipo de día Probabilidad según la referencia Esperados en 119 días Observados
ningún evento 0.68% 0.81 19
exactamente 1 evento 3.39% 4.04 63
4, 5 o 6 eventos 49.72% 59.17 4
12 o más (cuantil del 99% de la referencia: 11) 0.54% 0.64 11

El cuantil del 99% es el menor k con P(0) + … + P(k) ≥ 0.99. Llamaremos días de ráfaga a los 11 días que lo superan. El más cargado, el 2026-03-22, reúne 109 eventos; la referencia asigna a un día al menos igual de cargado una probabilidad de 6.32 × 10⁻¹⁰³. Una cifra así significa que la referencia es una descripción equivocada, no que haya ocurrido algo casi imposible.

Controles sintéticos. El mismo código devuelve D = 0.0017 para 594 eventos repartidos por igual entre 119 días, y D = 1.23, compatible con 1 dentro de la variación debida al azar, para un registro generado con semilla fija en el que cada evento cae en un día sorteado con probabilidad uniforme. Los tres registros comparten la media 4.99: la media no permite distinguirlos.

Con n = 119, Σx = 594 y Σx² = 26,390, calcule s² y D, y diga después a cuántas desviaciones estándar por encima de 1 se encuentra D.

Respuesta: (Σx)² / n = 352,836 / 119 = 2,965.01, de modo que s² = (26,390 − 2,965.01) / 118 = 23,424.99 / 118 = 198.52 y D = 198.517 / 4.9916 = 39.77. Con sqrt(2 / 118) = 0.1302, (39.77 − 1) / 0.1302 = 297.8 desviaciones estándar: una tasa constante no es una hipótesis candidata.

Calcule P(0) y P(1) según la referencia y el número esperado de días de cada tipo en 119, y compárelos con el registro.

Respuesta: exp(−4.9916) = 0.006795 y 119 × 0.006795 = 0.81 días vacíos esperados frente a 19 observados, 23.5 veces más. 4.9916 × 0.006795 = 0.03392 y 119 × 0.03392 = 4.04 días de un solo evento esperados frente a 63 observados, 15.6 veces más. El registro tiene demasiados días vacíos, de un solo evento y de ráfaga, y le falta la zona intermedia: los días que se parecen a la media.

Calculado a partir de los tipos de evento.

Un reloj. De los 63 días de un solo evento, 58 contienen un único discussion_created, con marca de tiempo entre las 13:51 y las 16:09 UTC, 56 de ellos en días laborables. De los 85 días laborables, 81 tienen al menos un discussion_created. Es compatible con una tarea programada; una candidata, streeling-daily.yml, se ejecuta de lunes a viernes a las 13:17 UTC y publica discusiones. Un disparador no registra qué discusión vio, así que la atribución es una inferencia.

Fines de semana vacíos o muy cargados. De los 19 días vacíos, 15 son sábados o domingos; también lo son los cuatro días más cargados, cuyas ráfagas son de más de un tipo:

Día Eventos push issue_opened discussion_created
2026-03-22, domingo 109 32 38 39
2026-06-28, domingo 72 4 34 34
2026-03-21, sábado 60 41 6 13
2026-06-27, sábado 45 0 21 24

Observado. La ficha del proyecto anti-pattern-003-push-triggered-spam describe flujos de trabajo que «trigger on every push to master, causing duplicate runs when a session has many commits» (se disparan con cada push a master y duplican ejecuciones cuando una sesión tiene muchos commits). Sitúa el patrón en el 2026-03-21 y el 03-22 (2 apariciones), lo detecta con «Workflow runs > 3 in a single day for the same workflow» (un umbral sobre las ejecuciones diarias de un mismo flujo de trabajo) e informa de una corrección en un flujo de trabajo el 03-22.

Calculado. En esos dos días, el registro es compatible con la ficha: 41 y 32 eventos push. Pero los push son 77 de los 286 eventos de los cuatro días más cargados, el 26.92%, por debajo de su proporción en el conjunto del registro (207 de 594, el 34.85%).

Cada archivo de la carpeta de archivados corresponde a una ejecución del flujo de trabajo productor, concebido para ejecutarse una vez por evento. Aplicado literalmente a él, el umbral de la ficha se supera en 21 días, 18 de ellos posteriores al 03-22. Observe la forma de la regla: un umbral sobre un recuento diario, no sobre una media.

Clasifique tres días: (a) 2026-03-21, 60 eventos, de ellos 41 push; (b) 2026-06-27, 45 eventos, ningún push; (c) 2026-04-07, un martes con un discussion_created a las 13:54 UTC. ¿Cuáles describe la ficha push-triggered-spam y cuáles señalaría su regla?

Respuesta: (a) Descrito y señalado: una ráfaga de push en una fecha que la ficha menciona, y 60 > 3. (b) Señalado, ya que 45 > 3, pero no descrito: ningún push; la ráfaga son 21 incidencias y 24 discusiones. (c) Ninguna de las dos cosas: una sola ejecución, a la hora de una programación de días laborables. Detrás de una sola media hay tres patrones; una corrección dirigida a los push no habría afectado a (b).

4. Las ventanas más largas no salvan la media

Sección titulada «4. Las ventanas más largas no salvan la media»

Un remedio natural es planificar por semanas y dejar que las ráfagas se compensen en el promedio. Divida los 119 días en 17 bloques de 7 días a partir del primero:

176 38 8 13 7 5 14 6 15 6 6 6 8 63 204 11 8

Calculado. En promedio, un bloque contiene 34.94 eventos, y el bloque mediano, 8 (el cuantil del 50%; con el método del rango más cercano, nearest rank, el cuantil de nivel p es el k-ésimo más pequeño de n valores, con k = p × n redondeado hacia arriba). El D de los bloques es 104.41, mayor que el de los días; un proceso de Poisson daría alrededor de 1 con cualquier longitud de ventana. Un índice que crece con la ventana significa que los días cargados llegan en rachas: los 11 días de ráfaga forman dos episodios (los días de ráfaga separados por 7 días como máximo cuentan como un solo episodio, una decisión de análisis), tres días entre el 03-21 y el 03-27 y ocho entre el 06-21 y el 07-02, separados por 86 días.

El total por bloque se duplicó como mínimo en 4 de los 16 pasos entre bloques vecinos, así que una regla de duplicación como la de PSY-002 necesita una línea de base que tenga en cuenta las ráfagas. La propia media está mal determinada: su error estándar, sqrt(variance / n), sería 0.20 con la varianza de la referencia de Poisson (la media), y es 1.29 con s² y 2.09 a partir de los bloques, sqrt(s²_blocks / 17) / 7. Tampoco depende el resultado de la medianoche UTC: si se desplaza el límite del día 6, 12 o 18 horas, D queda entre 47.58 y 64.09 y la mediana sigue en 1.

Con qué planificar en su lugar (calculado): días vacíos, el 15.97%; días con 2 eventos como máximo, el 79.83%; mediana 1, cuantil del 90% igual a 8, cuantil del 95% igual a 24, máximo 109; días de ráfaga, 11 de 119, en dos episodios. PSY-009 dimensiona un plan con un cuantil de este tipo.

La objeción más fuerte a esta lectura: para un total sobre un horizonte largo, la tasa media es la magnitud adecuada sea cual sea la dispersión, ya que total esperado = tasa × tiempo. Eso solo se cumple si los próximos meses se parecen a estas 17 semanas, e incluso entonces la tasa es 4.99 con un error estándar cercano a 2.09, porque 11 días de ráfaga reúnen 433 de los 594 eventos. Esta muestra no permite distinguir un proceso que produce ráfagas cada pocos meses de otro que tuvo dos ráfagas por motivos sin relación entre sí. La próxima comprobación lo zanjaría.

Un compañero de equipo propone «unos 35 eventos por semana, con un margen del 20% arriba o abajo». ¿Cuántos de los 17 bloques caen dentro de esa banda? Enuncie un criterio para aceptar una media como descripción para planificar, y aplíquelo.

Respuesta: Un 20% alrededor de 34.94 va de 27.95 a 41.93; un bloque de los 17 (38 eventos) queda dentro, y el bloque mediano contiene 8. Criterio: aceptar la media cuando los recuentos se dispersan a su alrededor como lo haría una tasa constante, con D a menos de dos desviaciones estándar de 1 en la ventana con la que se planifica. Para 17 bloques, sqrt(2 / 16) = 0.35, de modo que D debería quedar entre 0.29 y 1.71; vale 104.41. Rechace la media; planifique con la proporción de días vacíos, la mediana y los episodios de ráfaga.

Observado, fijado en Demerzel 4b03838800dcd4894f1e026461979bff1d985ca8: los 594 archivos de disparadores archivados (árbol de Git 2da37c16496d39c0c9137897c8be2b0c6d6b7978; la huella del manifiesto está en observed-input.json), la ficha del patrón y los dos archivos de flujo de trabajo enlazados más arriba.

Fixture. En esta carpeta de datos y scripts, que reproduce las cifras de la lección, scenarios.json recoge las decisiones de análisis, y el README da los comandos, las autocomprobaciones y los controles.

Referencias de método. Cox, D. R., y Lewis, P. A. W. (1966), The Statistical Analysis of Series of Events, Methuen (el índice de dispersión y su prueba). Barabási, A.-L. (2005), «The origin of bursts and heavy tails in human dynamics», Nature 435, 207–211 (tiempos entre eventos, que aquí no se analizan).

Límites y lo que no se hizo. Un solo repositorio y 119 días, la vida útil de un único flujo de trabajo productor; dos episodios no permiten decir con qué frecuencia se producen las ráfagas. Una marca de tiempo indica cuándo escribió el productor el archivo. Doce archivos de disparadores se borraron del repositorio sin archivarse (siete con fecha 2026-03-20, cinco con fecha 2026-06-30, ninguno en los cuatro días más cargados); PSY-009 los cuenta, y con ellos la media sería 5.09 y D, 39.40. No se comprobó si se perdieron otros por ejecuciones solapadas. No se ajustó ningún modelo de recuento (PSY-022), no se calculó ninguna medida de concentración (PSY-009) ni se estableció la causa de ninguna ráfaga. Ninguna persona ha revisado el fondo de esta lección y ningún aprendiz la ha probado.

Próxima comprobación. Contar por día los push, las incidencias y las discusiones a partir del propio historial de eventos de GitHub durante un periodo más largo, con la causa de cada día de ráfaga. Si las ráfagas se repiten con una separación y un tamaño estables, un reloj de días laborables más los episodios se convierte en un plan utilizable; si no, el plan honesto es una alarma por umbral, no un pronóstico.