CreaRack-SL

El auto-update del Agente aprende a esperar al antivirus: se acabaron las actualizaciones rotas (v1.45.11 · Agent 2.13.5)

Resumen ejecutivo

Problema: El auto-update del Agente corría más rápido que el antivirus. Cuando el Agente descargaba y ejecutaba una versión nueva en segundos, Windows Defender aún estaba analizándola “en la nube” — la extracción del onefile quedaba retenida/congelada, causando arranques “vivos pero no respondiendo” que el watchdog confundía con fallos y hacía rollback de versiones buenas (s201: diagnosticado 05-07-2026 con el primer rescate autónomo real).

Solución: Tres piezas en Agent 2.13.5 (terminal/agent/core/updater.py):

  1. Prescan explícito de Defender del binario descargado (antes del swap)

    • MpCmdRun -Scan -ScanType 3 -File, síncrono, best-effort
    • Replica el “tiempo muerto” entre descarga y ejecución que hace fiable a la instalación manual
    • Sin Defender (otro AV, MpCmdRun ausente), se salta
  2. Watchdog paciente — WaitHealthy con sondeo cada 10 s

    • Ventanas: 150 s (primer arranque) / 120 s (retry) / 120 s (post-rollback)
    • Antes: checks únicos a 30+20 s → mataba arranques vivos retenidos por el análisis
    • Ahora: el vigilante respeta el tiempo del análisis cloud
  3. version.txt auto-reconciliado al arrancar

    • Tras un rollback, el binario restaurado viejo no toca version.txt
    • En el siguiente arranque, cleanup_old_exe() comprueba que version.txt coincida con AGENT_VERSION
    • Evidencia del bug: 05-07-2026, version.txt=2.13.4 con 2.13.3 corriendo

Cambios técnicos

terminal/agent/core/updater.py

_defender_prescan(path) (nueva función):

  • Busca MpCmdRun.exe en %ProgramFiles%\Windows Defender
  • Lanza escaneo síncrono con timeout 180 s
  • Return codes: 0 (limpio) / 2 (amenaza detectada, self-test posterior fallará y el swap se aborta)
  • Si MpCmdRun no existe, se salta con traza "prescan Defender omitido"
  • Best-effort: nunca bloquea el ciclo de actualización (exceptions capturadas)

_apply_swap() (modificado):

  • Llama a _defender_prescan(NEW_EXE) antes de _selftest_new_exe()
  • Orden: prescan → self-test → swap

Watchdog PowerShell (modificado — _launch_swap_watchdog):

function WaitHealthy($secs) {
  # Poll cada 10s durante $secs segundos (antes: checks únicos)
  $until = (Get-Date).AddSeconds($secs)
  while ((Get-Date) -lt $until) {
    if (Healthy) { return $true }
    Start-Sleep -Seconds 10
  }
  return (Healthy)
}
  • Primer arranque: WaitHealthy 150
  • Retry post-stop: WaitHealthy 120
  • Post-rollback: WaitHealthy 120 con logs diferenciados (HEALTHY vs “needs manual relaunch”)

cleanup_old_exe() (modificado):

  • Tras eliminar CreaRackAgent.old.exe, comprueba version.txt
  • Si no coincide con AGENT_VERSION, lo actualiza y loga "version.txt reconciliado (drift post-rollback)"

terminal/agent/version.py

AGENT_VERSION = "2.13.5"
  • Changelog documenta las 3 piezas
  • Nota: “Exige recompilar el .exe”

config/settings/base.py

APP_VERSION = "1.45.11"

tests/agent/test_agent_updater_trace.py (3 tests nuevos)

  1. test_watchdog_script_sondea_paciente_no_check_unico

    • Verifica que el script contenga WaitHealthy y “polling health up to 150s”
    • Regresión contra el comportamiento impaciente de 2.13.4
  2. test_defender_prescan_sin_mpcmdrun_no_revienta

    • Sin MpCmdRun, el prescan se salta sin error
    • Simula CI/Linux o AV alternativo
  3. test_cleanup_reconcilia_version_txt_tras_rollback

    • Verifica que version.txt sea actualizado por cleanup_old_exe()
    • Copia traza esperada en el log

Impacto de usuario

  • ✅ Reducción dramática de fallos de auto-update — el Agente ya no entra en carreras contra Defender
  • ✅ Sin certificados de pago — el prescan es best-effort, no introduce dependencias nuevas
  • ✅ Sin intervención manual — el watchdog paciente se recupera solo
  • ✅ Actualización transparente — distribución vía Hetzner, primera ejecución con instalación fresca (regla de oro del bootstrap)

Detalles de propagación

  • Status: v1.45.11 en HOLD en Hetzner (ejecutable no publicado aún)
  • Estreno: instalación fresca + validación E2E manos-fuera en el siguiente release
  • Cambios de ayuda: ninguno (el watchdog es interno)
  • Regresión: NO — las defensas anteriores (self-test + rollback del swap) se mantienen intactas

Diario de diagnóstico s201

  • Fecha: 05-07-2026
  • Observación inicial: La instalación manual del Agente nunca falla; el auto-update sí
  • Causa raíz: Entre descarga (navegador) y ejecución (doble clic) pasan MINUTOS → el análisis cloud de Defender termina; el auto-update ejecuta en SEGUNDOS → el análisis está a medias cuando se extrae el onefile
  • Síntoma: “process alive but not responding” en la traza — no era un crash, era retencion por análisis
  • Primer rescate autónomo: El watchdog de 2.13.4 intentó relanzar el Agente (era el propósito de s201), pero el sondeo impaciente (30+20 s únicos) mató arranques que estaban VIVOS esperando al análisis, haciendo rollback de binarios buenos
  • Cierre: 2.13.5 con prescan proactivo + sondeo paciente

Véase también

  • [[feature—terminal—traza-persistente-swap-auto-update]]
  • [[concept—general—como-funciona-el-mecanismo-de-auto-update-del-local-agent]]
  • [[entity—terminal—service—updater]]
  • [[decision—20260705—prescan-defender-antes-del-swap]]