# Validación de la entrega Fecha: 2026-09-18. Esta entrega es v1.0.2. Se ha validado localmente su código, pero **no se ha desplegado v1.0.2 en SmartOS**, no se ha activado `armed` y no se han enviado señales reales. El paquete conserva dos barreras de fábrica: `ACTION_MODE dry-run` y `--force-dry-run` en SMF; además no contiene reglas de zona `allow` y la instancia SMF está inicialmente deshabilitada. Nota cronológica: `CHECKPOINT.md`, añadido posteriormente al mismo paquete v1.0.2, conserva la evidencia de la validación nativa y operativa que se realizó después de este corte local. Esa evidencia posterior completa los pendientes de compilación, probe y logging continuo descritos aquí, pero mantiene `armed` como NO GO y no modifica el código de la entrega. ## Evidencia real recibida de SmartOS En el nodo real `o6hsmartos10`, v1.0.1 validó correctamente mediante `--probe --force-dry-run` las fuentes nuevas: - `swap_committed_pages` coincidió con `allocated + reserved` de `swap -s`. - `swap_physical_used_bytes` coincidió con la suma de `(blocks-free)*512` de `swap -l`: `67024888 - 58931824 = 8093064` bloques = 4.143.648.768 bytes. - `anon_pageout_pages` coincidió exactamente con la suma de `cpu:*:vm:anonpgout`: 6.553.284 páginas. No se sumaron también los duplicados `cpu_stat:*:cpu_stat*:anonpgout`. La ejecución persistente de v1.0.1 bajo SMF permaneció estable, muestreó cada segundo y clasificó correctamente `state=NORMAL`, `action_pressure=0`, `floor=0` con `nscan=0` y entre unas 589.193 y 602.818 páginas libres, muy por encima de `lotsfree=130875`. Sus deltas de 5 y 15 segundos fueron coherentes; por ejemplo, una caída rápida de libre y aumento de compromiso virtual no se confundieron con presión real mientras el scanner permaneció inactivo. Esa prueba descubrió el defecto corregido aquí: el daemon continuo v1.0.1 aún mostraba la nomenclatura antigua (`swap_ok`, `swap_alloc_pages`, `swap_reserved_pages`, `swap_available_pages`, `metric=swap_used_pages`) y no exponía `swap_physical_used_bytes`, `anon_pageout_pages` ni sus deltas. Por tanto, la evidencia real valida las lecturas nativas y la estabilidad básica, pero no el nuevo contrato de logging v1.0.2. Antes de armar nada debe repetirse la prueba continua en SmartOS. ## Comprobaciones de v1.0.2 - `make test` ejecuta pruebas de configuración, política y la ruta real del daemon con backend simulado. La prueba de logging genera 61 muestras a cadencia de 1 s y exige los tres pares de valor/flag, los deltas exactos 5/15/60 s de `swap_committed_pages`, `swap_physical_used_bytes` y `anon_pageout_pages`, y que no aparezca `swap_used_pages`. - La política cubre los seis estados, histéresis y huecos. Verifica que el crecimiento de swap físico por sí solo, el pageout por sí solo, o ambas señales con `freemem >= lotsfree` no corroboran presión. Juntas sólo pueden corroborarla bajo `lotsfree`; no autorizan acciones por sí mismas. - La ruta simulada confirma que dry-run registra `WOULD_ACTION` y realiza cero solicitudes de señal real. También cubre protecciones, revalidación, warmup, caché, fallos de muestra/log/identidad, límites y parada. - `make test-sanitize` ejecuta ambas suites con AddressSanitizer y UndefinedBehaviorSanitizer. En entornos donde LeakSanitizer no pueda operar por restricciones de ptrace se usa `ASAN_OPTIONS=detect_leaks=0` y se deja constancia explícita; esto no equivale a una comprobación de fugas. - `make portability` aplica C99 estricto, warnings como errores, `-fanalyzer` a cada unidad, sintaxis shell y XML bien formado. Los `tests/api-sketch` sólo comprueban consistencia C en Linux; no sustituyen cabeceras, ABI, enlace ni ejecución nativos de illumos. - Se inspecciona que producción no invoque `system`, `popen`, `exec*` ni `kill(2)`. Las pruebas no enlazan el backend nativo y no pueden enviar señales. Los resultados exactos de esta ejecución se guardan en `logs/policy-tests.log`, `logs/runtime-tests.log`, `logs/sanitizers.log` y `logs/portability.log`. ## Validación obligatoria pendiente en SmartOS 1. Compilar con cabeceras nativas (`gmake CC=gcc`), ejecutar `gmake test CC=gcc` y comprobar ELF de 64 bits y dependencias con `file`/`ldd`. 2. Ejecutar `svccfg validate` nativo. Instalar/importar sólo siguiendo el procedimiento del README y mantener `--force-dry-run`; no añadir UUID `allow`. 3. Repetir `--probe --force-dry-run` y contrastar las tres fuentes con `swap -s`, `swap -l` y `kstat cpu::vm:anonpgout`. 4. Bajo SMF, verificar en cada `event=sample`: `swap_committed_ok/swap_committed_pages`, `swap_physical_used_ok/swap_physical_used_bytes` y `anon_pageout_ok/anon_pageout_pages`. Confirmar líneas `event=delta` con los tres nombres exactos y ventanas 5/15/60; buscar y exigir cero apariciones de `swap_used_pages`. 5. Confirmar cadencia, recorrido `/proc`, identidades de zona, lock, rotación y recuperación del servicio durante carga natural. No generar presión artificial en producción. 6. La ruta PCKILL sólo debe ensayarse posteriormente en un laboratorio nativo desechable, con procesos y zonas expresamente creados para esa prueba. Esta entrega no autoriza ni realiza esa fase. ## Límites conocidos La atribución por RSS es heurística y sobrecuenta memoria compartida. Una señal puede no liberar memoria de inmediato y un supervisor puede recrear procesos. El presupuesto `/proc` es cooperativo; libkstat, libc, ZFS y el logging pueden bloquear. No hay `fsync` por muestra, por lo que un panic puede perder las últimas líneas. Las protecciones y presupuestos prevalecen incluso al floor. Este guard no constituye una garantía de evitar `pageout_deadman` ni un certificado para activar acciones en producción.