Supervisor
Q198 S1 (row 257, #1762): parsers for the host pressure inputs in design D4
(docs/plans/2026-10-21_q198-system-manager.md), and a pure evaluator that turns timestamped samples
into a hold or release decision. Nothing here samples the host, runs a process or timer, or enforces
anything. The live sampler, the Console view and admission are S2 and S3.
node --test packages/supervisor/tests/
Parsers
Each parser takes file text the caller already read. Text that isn't the shape the kernel writes throws
a SupervisorError with kind: "parse"; a sampler treats that as a missing signal.
| Export | Input | Returns |
|---|---|---|
parseLoadavg |
/proc/loadavg |
{ load1, load5, load15 } |
parseMeminfo |
/proc/meminfo |
{ memTotal, memAvailable, swapTotal, swapFree } in bytes |
parsePsi(text, resource) |
/proc/pressure/{cpu,memory,io} or a cgroup *.pressure |
{ some, full }, each { avg10, avg60, avg300, total }; full is null only for cpu |
parseCpuList |
/sys/devices/system/cpu/online, cpuset.cpus.effective |
how many CPUs the list names |
parseCpuMax |
cpu.max |
the quota in CPUs, or null for max |
parseMemoryMax |
memory.max |
bytes, or null for max |
parseMemoryCurrent |
memory.current |
bytes |
parseMemoryEvents |
memory.events |
{ oom, oomKill } |
parseVmstat |
/proc/vmstat |
{ pswpin, pswpout, oomKill }; oomKill is the host-only OOM counter, null when absent |
effectiveCpus({ online, cpuset, cpuMax }) is the smallest of the host count, the cpuset and the quota
at every cgroup level given; a fractional quota stays fractional. effectiveMemory({ meminfo, levels })
takes cgroup levels as { max, current } text. The limit is the smallest of MemTotal and every numeric
memory.max. Available memory is the smallest of MemAvailable and max - current at each limited level.
memory.current counts page cache, so this errs toward holding. With no cgroup input both functions use
the host's figures.
Evaluator
evaluate(state, sample, rules, { reconciled }) returns { state, decision }. It starts from
initialState(), which is held: no signal has been seen yet. Time is the sample's at in milliseconds.
The evaluator never reads the clock.
A sample has these signals: load { at, load1, cpus }, memory { at, available, limit },
psi { at, cpuSome, memoryFull, ioFull } (avg10 percentages), oom { at, kills } and disk { at, free }.
| Signal | Hold | Release |
|---|---|---|
load1 / cpus |
≥ 0.80 on 3 consecutive samples | ≤ 0.55 |
| available memory | < max(15% of limit, 1 GiB), on one sample | > max(25% of limit, 2 GiB) |
| PSI avg10 | cpu some ≥ 20, memory full ≥ 2 or io full ≥ 10, on 3 consecutive samples | cpu some < 10, memory full < 0.5 and io full < 3 |
| critical | OOM kill counter rises, memory < 5% of limit, or disk free < 1 GiB | the caller passes reconciled, then the normal release |
- Release needs every applicable release condition on every sample for 30 s. A dead-band sample (between hold and release) or a new hold restarts the window.
- Missing or stale: a required signal that is missing, malformed, more than 6 s older than the
sample, or later than it holds at once with
health-unknown.load,memory,oomanddiskare always required. PSI becomes required once a sample has carried it. A host without PSI skips the PSI rows, and one that loses it holds. - Consecutive counts reset after a gap of more than 6 s between samples. The PSI count runs across resources: any PSI hold condition on 3 consecutive samples holds.
- OOM: the first OOM sample is the baseline. A counter that falls (a recreated cgroup) resets the
baseline with the note
oom-counter-reset. - Critical never ends on thresholds alone.
reconciledonly counts once no critical condition remains, and the 30 s release still follows. The evaluator never sets it and never touches a kill switch. - A clock that goes backwards holds with
health-unknownand the noteclock-backwards.
decision is { mode, reasons, unknown, critical, releaseAt, notes }.
modeisopen,heldorcritical.reasonsarehealth-unknown,load-high,memory-low,psi-cpu,psi-memory,psi-io,hysteresis,release-pendingor the critical codescritical-oom,critical-memoryandcritical-disk.releaseAtis set while a release is pending.
DEFAULT_RULES is the D4 table, frozen. resolveRules(overrides) merges overrides key by key. It refuses
with kind: "rules" on an unknown key, a non-number or a contradictory pair, for example:
- a release threshold at or past its hold;
- a release floor at or below its hold floor;
- a critical memory fraction at or above the hold fraction;
- a stale limit at or below the sample interval. Provider scope (429, quota, Retry-After) is not here; it belongs to S3 and S5.