Skip to content

fix(tests): la espera de arranque del servidor MCP tiene que esperar de verdad - #250

Merged
wolverin0 merged 2 commits into
mainfrom
fix/hermes-http-fixture-espera-real
Aug 31, 2026
Merged

fix(tests): la espera de arranque del servidor MCP tiene que esperar de verdad#250
wolverin0 merged 2 commits into
mainfrom
fix/hermes-http-fixture-espera-real

Conversation

@wolverin0

Copy link
Copy Markdown
Owner

El flaky no era aleatorio

test_authenticated_mcp_http_delivers_disposable_capture cayó cuatro veces el 2026-08-31, siempre en Windows, con authority_unavailable. Entre 1 y 1,5 horas de suite cada vez, más el relanzamiento que vuelve a pagarla entera.

Los dos defectos

for _ in range(100):
    try:
        if httpx.get(health, timeout=0.2).status_code == 200: break
    except httpx.HTTPError:
        time.sleep(0.02)          # ← el sleep SÓLO acá
  1. Sin sleep en la rama "respondió pero no 200" — el caso normal mientras arranca. El bucle giraba sus 100 vueltas en milisegundos y se rendía sin haber esperado nada.
  2. El límite estaba en vueltas, no en tiempo. El presupuesto real dependía de si cada intento fallaba rápido o agotaba su timeout: no había presupuesto.

Por qué el síntoma mentía

El fallo no aparecía como un error de arranque legible. El test avanzaba, la llamada MCP fallaba, y _classify_transport_error (backend.py:273) la reportaba como authority_unavailable — que es su fallback para cualquier error de transporte sin clasificar. Por eso durante meses se leyó como "ruido de red".

Por qué NO un marker de reintento ni un job aparte

Opción Por qué no
Marker de reintento Exige una dependencia nueva: ninguna de pytest-rerunfailures, flaky ni pytest-retry está instalada. Y tolera el síntoma en vez de arreglarlo
Job aparte no bloqueante Tapa la caída por completo — nadie mira los jobs que no bloquean. Contradice el criterio del PR #249: el chequeo tiene que llegar a hablar

Este arreglo no tolera nada: le da al arranque el tiempo que el bucle decía darle y no daba.

Y hay un test que fija que no es un reintento: un servidor que nunca levanta sigue fallando.

Barra roja

Verificada contra el bucle original: caen exactamente los dos tests que anclan los defectos, y los otros tres pasan — porque ese comportamiento ya estaba bien. Un test que fallara con el código viejo y con el nuevo no estaría midiendo el defecto.

13/13 en la suite real de hermes, 5/5 en los nuevos, ruff limpio.

…de verdad

`test_authenticated_mcp_http_delivers_disposable_capture` cayo CUATRO veces el
2026-08-31, siempre en Windows, con `authority_unavailable`. Entre 1 y 1,5 horas
de suite cada vez, mas el relanzamiento que vuelve a pagarla entera.

NO era aleatorio. El bucle de arranque del fixture tenia dos defectos:

    for _ in range(100):
        try:
            if httpx.get(health, timeout=0.2).status_code == 200: break
        except httpx.HTTPError:
            time.sleep(0.02)          # <- el sleep SOLO aca

1. Sin sleep en la rama de "respondio pero no 200" —el caso normal mientras
   arranca— el bucle giraba sus 100 vueltas en milisegundos y se rendia sin
   haber esperado nada.
2. El limite estaba en VUELTAS, no en tiempo: el presupuesto real dependia de si
   cada intento fallaba rapido o agotaba su timeout. O sea que no habia
   presupuesto.

Por que el sintoma mentia: el fallo no aparecia como un error de arranque
legible. El test avanzaba, la llamada MCP fallaba, y `_classify_transport_error`
(backend.py:273) la reportaba como `authority_unavailable`, que es su FALLBACK
para cualquier error de transporte sin clasificar.

`_wait_until_healthy` reemplaza el bucle: limite por TIEMPO, sleep en todos los
caminos, timeout por intento de 1s en vez de 0,2s.

NO es un reintento y hay un test que lo fija: un servidor que nunca levanta
sigue fallando. No repite aserciones ni tolera un fallo persistente — que era el
riesgo de la alternativa que descarte (marker de reintento, ademas de exigir una
dependencia nueva; ninguna de pytest-rerunfailures/flaky/pytest-retry esta
instalada). La otra alternativa, un job aparte no bloqueante, tapa la caida por
completo, que contradice el criterio del PR #249: el chequeo tiene que llegar a
hablar.

Barra roja verificada contra el bucle ORIGINAL: caen exactamente los dos tests
que anclan los defectos y los otros tres pasan, porque ese comportamiento ya
estaba bien.

13/13 en la suite real de hermes, 5/5 en los nuevos, ruff limpio, release-truth
regenerado ANTES de commitear.
Los 8 PRs del dia, los resultados MEDIDOS (perfil destrabado tras 10 dias,
PPR-7 volviendo a emitir, corpus 18% -> 96% agrupado, cero claims vivas en
tenant NULL), los 9 items que quedan abiertos con su evidencia, y las seis
trampas que costaron tiempo hoy — incluida la de release-truth, en la que cai
cuatro veces.
@wolverin0
wolverin0 merged commit d86cd9b into main Aug 31, 2026
15 checks passed
@wolverin0
wolverin0 deleted the fix/hermes-http-fixture-espera-real branch August 31, 2026 20:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant