Skip to content

Corrección de normalidad y presupuesto N-1 — 2026-10-19

Última ventana completada: 22 oct, 08:51:07–10:51:07 CEST, boots a002/861. Envolvente conservadora observada −3,81 GiB tras reservar 2 GiB; comparación usando el máximo total de una ronda: −2,02 GiB. Demanda 121/121; oferta 480/481 puntos usables, con bordes sin observar. No se admite N−1. Mediciones, límites y próximos pasos. Las capturas instantáneas y boots anteriores se conservan como históricos.

Autorización: aplicar las mejoras de la revisión con agentes simultáneos. Ámbito de este cambio: comprobador de RAM/HA, sin modificar RAM asignada, políticas HA, cargas, ARC ni reiniciar huéspedes o hosts.

Cambio aplicado

Fuente: ansible/roles/proxmox_node/files/normalidad; desplegada como /usr/local/bin/normalidad en pmx-50 y pmx-51.

  • El OK usa exclusivamente MemAvailable destino − RAM+swap actual de HA migrables − 2048 MiB de reserva. No suma balloon al disponible.
  • Publica aparte un margen condicionado. Lee balloon efectivo y mínimo de Proxmox, no memory configurado − mínimo; cualquier memoria ya cedida no se vuelve a sumar. Solo considera información balloon de hasta 120 segundos.
  • Lee MemAvailable, swap y PSI full del invitado mediante QEMU Guest Agent. El techo adicional es min(balloon efectivo−mínimo, MemAvailable−512 MiB); con PSI full avg10 o avg300 >=1 %, datos ausentes/obsoletos o bajo disponible devuelve cero. Los 512 MiB son una guarda del indicador, no garantía de que el invitado tolere esa reducción. No se ejecuta ninguna reducción.
  • Muestra ambos sentidos incluso con cero HA migrables; enumera recursos estrictos y huéspedes activos fuera de HA. Las parejas C0 se comprueban aparte. Ni las exclusiones ni un margen positivo acreditan HA completa.
  • Publica límites RAM de los migrables y advierte que consumo actual no garantiza picos ni arranque simultáneo. La falta de medidas impide un OK.
  • Respeta failback=0 (HAOS171): residir en el otro nodo estando started no se trata como retorno automático pendiente.
  • Elimina touch /mnt/nfs_media/.normalidad. Comprueba acceso a metadatos y tipo/opciones de montaje mediante stat/findmnt, describiendo exactamente esa cobertura y sin afirmar una escritura probada.
  • El código es importable sin ejecutar consultas; permite probar el presupuesto de manera aislada.

Evidencia tras despliegue

Primera ejecución desde pmx-50, durante el trabajo paralelo del 19-oct:

Concepto MiB
Disponible pmx-50 13.498
Consumo RAM+swap de 10 HA migrables 11.912
Reserva 2.048
Margen sin balloon −462
Techo adicional condicionado de VM208 2.026
Margen condicionado +1.564
Límites RAM migrables 19.328

VM208: balloon efectivo 8192 MiB, mínimo 6144 MiB; disponible del invitado 2538 MiB; swap usada 2702 MiB; PSI full avg10/avg300 0,01/0,06 %. El comando sale 1 con AVISO, sin el falso OK previo. No se transforma el techo condicionado en capacidad ya disponible.

En ese momento los 14 HA estaban started, las 14 réplicas al día, 28 invitados cubiertos por job y todos con copia PBS de menos de 26 h. Quórum tres votos; watchdogs de hardware y kdump50 ready. Estos datos describen una muestra, no acreditan recuperación de todos los datos externos ni estabilidad prolongada.

Exclusiones por pérdida de pmx-51: estrictos 110/172/217/218; sin HA 200/204/271/301/302/303. Por pérdida de pmx-50, fuera de HA: 186/208/219/251/270/280/281/305. Los pares Caddy/DNS tienen su comprobación separada y pueden prestar cobertura de aplicación aunque no migre su huésped.

Validación y rollback

  • Cinco pruebas pasan en ansible/roles/proxmox_node/tests/test_normalidad.py: caso histórico de falso OK, balloon parcialmente cedido, reserva del invitado, datos ausentes/obsoletos/PSI elevado y separación de ambos márgenes.
  • Compilación Python correcta; despliegue temporal y renombrado atómico.
  • Copia previa en ambos nodos: /usr/local/bin/normalidad.pre-nminus1-20261019.
  • SHA256 anterior: <REDACTED>.
  • SHA256 desplegado: <REDACTED>.
  • Para volver: restaurar la copia previa sobre /usr/local/bin/normalidad; no requiere reinicio ni servicio. Eso recuperaría también las limitaciones del cálculo previo y su prueba de escritura NFS.

No se ha reducido VM208: quitar incluso 512 MiB dejaría un margen estimado muy pequeño en esta muestra. Se necesita un margen sostenido mediante capacidad física sana o una decisión explícita sobre qué cargas retirar durante una emergencia. Bajar límites sin liberar RAM real no arregla el presupuesto. La estabilidad de pmx-50 debe diagnosticarse antes de basar en él una ampliación o una nueva carga; este cambio mejora la veracidad del indicador.

Segunda ejecución desde pmx-51: salida 1, margen sin balloon −404 MiB, condicionado +1644 MiB. Ambos nodos ejecutan el mismo hash. Las diferencias entre muestras son normales y refuerzan que no debe dimensionarse al límite.

Procedimiento concreto para emergencia de capacidad en pmx-50

Se conserva el modo degradado C2 descrito en ADR-0026, sin crear un daemon, cron ni ampliar exclusiones HA. No se ha ejecutado este procedimiento ni parado ninguna carga. Los candidatos operativos se limitan a RAG251 y Homelable305 tras revisar trabajo activo. CT281 queda excluido: no está aclarado si contiene sitios de clientes o de Carmelo, que está fuera del alcance autorizado.

Muestra en vivo de candidatos fuera de HA:

CT Función perdida al apagarlo RAM cgroup Swap Anon residente
251 RAG de Vera, Kiwix y servidor ZIM ~1455 MiB ~187 MiB ~757 MiB
305 Homelable y su servidor MCP ~286 MiB 0 ~173 MiB

memory.current incluye caché de archivos, que puede estar contabilizada ya en MemAvailable. Tampoco la swap libera RAM equivalente al apagar. Por eso no se suman RAM+swap como ganancia: anon residente aproxima la parte privada que se dejaría de usar, sin garantizar el delta de MemAvailable. Medirlo después es obligatorio. RAG y Homelable sumaban ~930 MiB de anon en la muestra; esa cifra no acredita un margen amplio sobre los picos actuales. A modo de inventario, CT281 usaba ~1674 MiB RAM (~1245 MiB anon), pero no forma parte del procedimiento: preservar sus cuatro sitios y bases de datos hasta aclarar propiedad y autorización.

Todos tienen onboot=1; un reinicio de pmx-50 los arrancaría de nuevo. Se observaron timers de indexación RAG, backup/riesgo/spam WP y tareas del sistema. No se encontró un controlador existente que desactive estas cargas por falta de RAM; node-autowake arranca nodos, no resuelve esta reserva. No se amplió su función ni se alteraron timers. Una sesión en maint o SSH puede ejecutar el procedimiento usando los comandos Proxmox existentes.

  1. En el nodo superviviente, comprobar pvecm status, ha-manager status, pct status <id> y tareas activas del nodo/CT en Proxmox. Confirmar que no está corriendo backup/restauración o una operación de mantenimiento. Si se opta por CT251, inspeccionar antes pct exec 251 -- systemctl is-active homelab-rag-indexer.service homelab-rag-fast.service; no cortar una tarea a ciegas. No detener PBS186, VM208, Caddy270 ni cloudflared219 como atajo.
  2. Elegir CT251 o CT305 si su pérdida es aceptable; comprobar también las sesiones MCP/trabajo activo antes de suspender Homelable. Usar apagado ordenado, por ejemplo pct shutdown 251 --timeout 60 en pmx-50. Si falla, investigar; no añadir --forceStop ni usar pct stop automáticamente. No apagar CT281: su posible relación con clientes/Carmelo impide incluirlo en este procedimiento sin aclaración adicional.
  3. Comprobar pct status <id>, free -m y normalidad. El resultado nuevo decide si se ha liberado suficiente RAM real. Con HA ya recuperado en50, revisar también la reserva libre del propio50: origen51 vacío no es una prueba de que50 tenga margen. No esperar que MemAvailable suba la suma íntegra de RAM+swap de la tabla.
  4. Cuando51 esté sano y sus recursos hayan vuelto conforme a las políticas, revisar de nuevo memoria/PSI antes de pct start <id>. Arrancar de uno en uno y comprobar función de la aplicación y timers. HAOS171 tiene failback=0: puede permanecer deliberadamente en50; no forzar su migración como parte de restaurar estas cargas. Si50 reinicia durante el modo degradado, revisar inmediatamente el onboot y la reserva porque los CT volverán a arrancar.

Este procedimiento ofrece una respuesta manual reversible para una emergencia; no reserva memoria por anticipado ni convierte el clúster en tolerante a picos.

Observación posterior al reinicio de pmx-51

La comprobación central a las 22:02 devuelve NORMAL, con margen sin balloon +5035 MiB y solo 6140 MiB de HA migrables tras el arranque en frío. Las muestras anteriores con carga caliente sumaban ~11.900–12.900 MiB de RAM+swap. La liberación de swap/cachés al reiniciar cambia la foto: este OK acredita el consumo actual, no capacidad garantizada cuando las aplicaciones vuelvan a crecer ni picos de arranque. No se ha alterado el algoritmo para convertir esa mejora transitoria en una garantía; conservar el seguimiento y el procedimiento manual anterior.

Muestra conjunta nativa: 21 octubre, 11:03 CEST

Una lectura paralela y acotada en ambos hosts entre 11:03:02,018343 y 11:03:10,902747 CEST mide el conjunto migrable actual sin ejecutar normalidad, colectores, NAS, aplicaciones o acciones de HA. El margen del criterio existente resulta negativo: −2.207,95 MiB tras reservar 2 GiB. Esta muestra sustituye la falta de demanda contemporánea señalada a las 10:41; no convierte los valores positivos históricos en capacidad garantizada.

Antes y después de cada captura se comprobaron hostname, boot e inventario PVE, recursos HA y afinidades. Pmx50 conserva <REDACTED_UUID>; pmx51 <REDACTED_UUID>. Se mantienen 28 invitados running, 14 recursos HA configurados started en pmx51 y los mismos digests de recursos y reglas. La regla migrable contiene exactamente100/123/155/171/212/213/214/215/ 216/220; 110/172/217/218 siguen estrictos en pmx51. Ninguno de los ocho invitados de pmx50 pertenece al HA registrado; por perder pmx50 no entra demanda HA adicional en pmx51, sin que eso recupere sus servicios sin HA.

Método comparable con el comprobador existente

  • Para los nueve LXC migrables: memory.current + memory.swap.current del cgroup nativo de cada invitado, una sola vez. Se guardaron identidad del cgroup y campos seleccionados anon/file/kernel de memory.stat para describir su composición; no se suman esos campos otra vez.
  • Para VM171: VmRSS + VmSwap del proceso QEMU del PID file existente, con PID y start ticks iguales durante cada lectura. No se accedió al guest ni a la API/shell de Home Assistant, ni a la aplicación o cambios de Vera.
  • Cada host tomó dos lecturas locales consecutivas. La demanda usa el máximo por invitado de ambas; destino usa el menor MemAvailable. Es una envolvente conservadora de la captura, no una transacción atómica entre nodos ni una observación prolongada de picos.
  • Reserva 2.048 MiB; cero crédito adicional de balloon, ARC o caché. No se usa maxmem ni mem de la API como RSS. MemAvailable del destino ya incorpora su propia estimación de memoria recuperable.

Los LXC incluyen caché de archivos y memoria de kernel cargada a su cgroup, no sólo RSS de procesos. La swap se cuenta como demanda que podría volver a RAM; no se presenta como RAM física residente hoy. QEMU RSS incluye memoria del proceso y su sobrecoste, no equivale al target balloon ni a la memoria útil del guest. Mezclar estas medidas reproduce el presupuesto conservador del comprobador existente, pero no predice exactamente lo que costará un arranque frío o la transferencia de cachés al destino. No se promete que toda caché pueda descartarse para obtener admisión.

Recurso migrable RAM+swap computada MiB Swap incluida MiB
CT100 4.617,20 893,82
CT123 97,89 0
CT155 91,34 0
VM171, QEMU 6.170,57 0
CT212 122,51 0,004
CT213 91,21 0,004
CT214 209,63 0,004
CT215 389,81 0,004
CT216 127,83 0,004
CT220 1.771,84 33,25
Total, suma de bytes antes de redondear 13.689,8125 —

Pmx50 tomó memoria a las 11:03:04,799058–11:03:04,799213; pmx51 a las 11:03:06,387088–11:03:06,393171. La diferencia entre los instantes de medición es de unos 1,59 s, dentro de la ventana de inventarios anterior. El QEMU de VM171 conserva PID 5918/start ticks 4636; las identidades de los nueve cgroups también coinciden. La PSI de memoria some/full avg10/60/300 es 0,00 % en ambos hosts en esas muestras; no acredita ausencia de presión durante una recuperación ni identifica la causa de los resets.

Presupuesto reproducible

Concepto Bytes MiB
MemAvailable mínimo del destino pmx50 14.187.094.016 13.529,8671875
Demanda de los diez migrables 14.354.808.832 13.689,8125
Reserva 2.147.483.648 2.048
Margen sin balloon −2.315.198.464 −2.207,9453125

Fórmula: 14.187.094.016 − 14.354.808.832 − 2.147.483.648 bytes. Incluso sin reserva la resta sería −159,9453125 MiB. Esto no demuestra OOM inevitable, porque caché, swap, arranque y sobrecostes no evolucionan de forma idéntica a esa suma; sí impide declarar admitido el N-1 por el criterio actual. Faltan capacidad sostenida y margen de picos, no otra resta de máximos teóricos.

No se tocaron límites, balloon, afinidades, servicios, cachés ni trabajos. Los únicos candidatos manuales de degradación siguen siendo RAG251 y Homelable305 tras revisar trabajo activo y pérdida aceptada, con medición posterior real: sus consumos históricos no garantizan liberar los 2.207,95 MiB. CT281 no se añade; tampoco se levantan los cuatro estrictos. La prioridad es reducir exposición mediante capacidad sana o un conjunto esencial explícito, además de resolver la inestabilidad de pmx50; no recortar RAM para fabricar OK.

Evidencia privada: directorio 0700 ~/.local/state/nminus-native-20261021-m008irxm/, proyecciones 0600. Sin env, credenciales, cmdline o datos de aplicaciones:

Archivo SHA256
pmx.json <REDACTED>
pmx2.json <REDACTED>
calculation.json <REDACTED>
degraded-candidates.json <REDACTED>

Candidatos de degradación: lectura de las 11:05 CEST

Una lectura nativa posterior entre 11:05:15,809079 y 11:05:17,649788 CEST revalidó CT251/305 running en pmx50 y el mismo boot antes/después; sólo leyó cgroups, memoria del host y propietarios PVE. No inspeccionó aplicaciones, sesiones ni trabajos activos y no apagó ninguno.

Candidato memory.current MiB swap MiB Suma contable MiB anon residente MiB file MiB
CT251 RAG 1.252,86 39,88 1.292,73 900,36 330,30
CT305 Homelable 239,83 0 239,83 173,99 56,96
Total sin redondear 1.492,69140625 39,875 1.532,56640625 1.074,34375 387,26171875

anon y file son componentes descriptivos, no ganancias que sumar a memory.current. La swap no libera RAM equivalente al apagar; parte de file y slab recuperable puede estar ya considerada en MemAvailable. Ni siquiera la suma contable completa de ambos candidatos, 1.532,57 MiB, alcanza el déficit de referencia de las11:03 de2.207,95 MiB: quedarían675,38 MiB bajo esa hipótesis. Las mediciones están separadas unos dos minutos y no se combinan para afirmar un margen simultáneo nuevo. La memoria disponible de pmx50 en la lectura de 11:05 era13.592,4609375 MiB; no se volvió a medir entonces la demanda migrable. Estos datos no justifican prometer que apagarlos resolverá la admisión.

Plan de admisión sin cambiar cargas en esta revisión:

  1. Mantener el conjunto actual de diez migrables y las cuatro exclusiones. No se propone ninguna acción sobre Vera ni sobre sus cambios paralelos.
  2. Para el consumo de referencia, el destino necesitaría al menos 15.737,8125 MiB disponibles (13.689,8125 de demanda +2.048 de reserva), antes de margen adicional para crecimiento/arranque y diferencias de plataforma.
  3. Evaluar capacidad física sana o una decisión explícita de qué funciones esenciales deben recuperarse. No ampliar afinidades ni reducir targets a ciegas; los dos candidatos actuales por sí solos no acreditan la solución.
  4. En una intervención de degradación, revisar primero trabajo/sesiones y pérdida aceptada; después del apagado ordenado permitido medir de nuevo demanda, MemAvailable y PSI conjuntamente. Sólo ese resultado, seguido de observación representativa, puede acreditar reserva. No dar por liberada la tabla anterior.

Lector de inventario corregido y convergencia ordinaria, 21oct11:27

La PR96, main 74f705c, corrige el rechazo de la línea válida fencing armed (CRM watchdog active). Dieciocho regresiones y replay del estado nativo guardado pasan; se mantienen rechazos de estados desconocidos/desarmados, duplicados e incoherentes, junto con todas las guardas de propietario/tipo/estado y la reserva del presupuesto.

Ambos hosts recibieron el archivo por sus ciclos ordinarios: pmx50 11:22:00–11:22:48 y pmx51 11:25:29–11:26:28 CEST, success/rc0. La segunda invocation <REDACTED> se siguió hasta terminar; no se tomó el estado activating como éxito. A las 11:27:11 ambos conservaban sus boots del baseline y archivo root/0755/nlink1, 24.460 bytes, SHA256 <REDACTED>.

No se ejecutó normalidad completo, que incluye otros accesos; el hash prueba instalación, no salud global ni salida funcional del script. La medida N-1 negativa anterior procede de lecturas nativas independientes, no de ese hash. Recibos privados en ~/.local/state/normalidad-convergence-20261021-qsvuvuib/: pmx-first-cycle.json SHA <REDACTED>, pmx2-completed-cycle.json SHA <REDACTED>.

Revisión local de demanda desconocida, 21oct13:30

La lectura nativa de las11:03 sigue siendo histórica (boot pmx50 c4c64375…), no se ha vuelto a consultar para esta revisión. La política vigente conserva los diez migrables y las cuatro exclusiones estrictas. Desglosar la demanda no cambia qué funciones forman parte del presupuesto:

Composición de los diez migrables RAM+swap observada MiB Límites RAM MiB
Control/acceso:123/155/212/213/214/215/216 1.130,20703125 3.968
Home Assistant171 6.170,5703125 6.144
Vera100, sin intervención 4.617,19921875 6.144
Jellyfin220 1.771,8359375 3.072
Conjunto vigente completo 13.689,8125 19.328

El RSS del QEMU incluye sobrecoste del proceso: puede superar la RAM configurada; esta última tampoco es un techo del coste completo de arranque. Con la reserva 2.048MiB, hacen falta15.737,8125MiB disponibles para la demanda observada, frente a13.529,8671875: déficit2.207,9453125MiB. El presupuesto de límites más reserva es 21.376MiB, antes de sobrecostes. No se suma ARC, balloon, caché ni swap como ahorro.

La fuente de normalidad tenía un defecto independiente de ese déficit: awk podía emitir0 desde END al fallar la lectura del status de QEMU; el echo exterior ocultaba el error. Además, una lectura fallida de swap LXC se sustituía por0. Una medida incompleta podía pasar por una demanda cero. La corrección omite la fila si faltan/son inválidos RAM o swap; exige ambos campos QEMU únicos, numéricos y en kB. Un comando de medida con rc distinto de0 no acredita ninguna de sus filas. Un cero medido válido sigue siendo cero. El mecanismo existente marca entonces demanda ausente/AVISO, sin cambiar fórmula, exclusiones ni reserva.

Veintitrés pruebas offline pasan con Python3.12: ejecutan el comando real sobre un árbol sintético local (sin /proc real ni SSH), separan cero válido de archivos inexistentes/campos inválidos/duplicados y recorren el bloque real N-1 para el rc fallido con stdout parcial. Las mismas regresiones fallaban contra la fuente anterior. Evidencia privada ~/.local/state/n1-missing-demand-proof-20261021-4ktgsf3j/.

No hay ahorro real demostrado en estos recibos sin perder funciones. RAG251 y Homelable305 no cubren el déficit ni siquiera por su suma contable completa; la caché no es una reserva adicional. La siguiente acción es admitir el lector corregido y obtener otra muestra conjunta con el epoch actual antes de decidir capacidad sana o una reducción de carga específica medida. No se reducen RAM, afinidades o funciones para convertir el resultado en PASS. Esta corrección de fuente no se ha desplegado: al integrarse, Ansible-pull puede copiar el comprobador; no ejecuta el chequeo ni cambia memoria por sí mismo.

Muestra del epoch558, 21oct13:44–13:45

Nueva captura nativa entre13:44:49,792 y13:45:10,081 CEST, sin normalidad global, NAS, guestexec/HAOS ni cambios de memoria. Los cuatro inventarios mantienen14HA/diez migrables/cuatro estrictos, propietarios y políticas; boots pmx50 558fbd3c… y pmx51 86184726… estables. Dos lecturas por nodo usan máximo RAM+swap por invitado y mínimo MemAvailable del destino, con identidades de cgroup y PID/start QEMU comprobados.

Criterio sin crédito adicional de balloon MiB
MemAvailable mínimo pmx50 13.582,52734375
Diez migrables, RAM+swap 13.663,17578125
Reserva 2.048
Margen −2.128,6484375

Sigue sin admitir N-1. El resultado no acredita OOM inevitable, carga máxima, arranque conjunto ni pérdida funcional. Tampoco demuestra ahorro causal frente a las11:03. Se conservan los19.328MiB de límites y21.376MiB con reserva, antes de sobrecostes; no se redefine el núcleo para obtener un PASS.

La metadata PVE171/208 se enlazó al PIDfile y start_ticks antes/después;171 coincide además con el proceso que aporta RSS. HA171 mantiene máximo6144MiB, target/actual5632MiB; VM208 máximo8192MiB, target/actual7680MiB. shares0 y last_update durante esta captura acreditan5,5/7,5GiB efectivos, no otro1GiB incremental liberado en el host. Se cuenta una sola vez la demanda observada.

El primer lector devolvió UNKNOWN en ambos hosts: esperaba int para memory, pero la API nativa devuelve string numérico. Se corrigió mediante normalización estricta, fixtures y peer antes de repetir la captura completa. No fue fallo RAM/HA; los recibos fallidos no se sustituyen ni se usan como cero.

Recibos privados en ~/.local/state/nminus-native-epoch558-20261021-t911w2hp/:

Archivo SHA256
calculation.json <REDACTED>
pmx-fixed.json <REDACTED>
pmx2-fixed.json <REDACTED>

No se cambiaron RAM, balloon, afinidades, invitados, cachés o trabajos. La siguiente decisión de capacidad sigue necesitando preservar funciones y margen de arranque/picos; este snapshot no convierte una optimización contable en capacidad física disponible.

Muestra del epoch74, 21oct14:37–14:38

Captura conjunta nativa entre 14:37:40,674 y14:38:04,664 CEST, con pmx50 <REDACTED_UUID> y pmx51 <REDACTED_UUID> estables antes/después. Los cuatro inventarios son idénticos:14HA, diez migrables y cuatro estrictos con los mismos propietarios/políticas. Dos lecturas conservan cgroups y PID/start de QEMU; el máximo por invitado de RAM+swap y el mínimo MemAvailable del destino se combinan con la misma reserva2048MiB. No hay crédito de caché, ARC o balloon.

Criterio sin crédito adicional de balloon MiB
MemAvailable mínimo pmx50 13.693,953125
Diez migrables, RAM+swap 13.652,6328125
Reserva 2.048
Margen −2.006,6796875

Sigue sin admitir N-1 por este criterio. No acredita OOM inevitable, demanda máxima ni arranque simultáneo; no atribuye una ganancia causal al reset. Los límites de los migrables siguen sumando19.328MiB,21.376MiB con reserva, antes de sobrecostes. CT100 sólo se leyó como demanda cgroup, sin inspeccionar la aplicación Vera. No se ejecutó normalidad general, guestexec, HAOS ni NAS.

PVE y PIDfile enlazan VM208 PID4919/start3714 y VM171 PID5918/start4636, sin cambios antes/después. VM208 conserva máximo8192MiB y target/actual7680MiB; VM171 máximo6144MiB y target/actual5632MiB. shares0 y last_update durante la captura acreditan el balloon actual del nuevo epoch, sin sumar otro1GiB de ahorro incremental en el host ni utilizar maxmem como RSS.

Recibos privados en ~/.local/state/nminus-native-epoch74-20261021-zoq8yg3o/:

Archivo SHA256
calculation.json <REDACTED>
pmx-fixed.json <REDACTED>
pmx2-fixed.json <REDACTED>
reader-fixed.py <REDACTED>

El lector sólo cambia el boot explícitamente admitido respecto al validado anterior; nueve fixtures locales pasan. El cálculo reproduce exactamente filas, disponible, demanda y margen del recibo13:45 antes de calcular el nuevo. UNKNOWN sigue siendo rechazo, nunca cero. No se escribieron configuraciones ni se modificaron RAM, afinidades, cargas o invitados.