From 5c5e1f797c5d8dfba6291dcb66031d5b25e58123 Mon Sep 17 00:00:00 2001 From: Bernardo Magri Date: Fri, 10 Jul 2026 14:51:59 +0100 Subject: [PATCH] docs(agent): #76 require VM hibernate verify; LUKS+@swap reference Agent must V2-test hibernation in the VM (encrypted BTRFS @swap swapfile). Reference layout from live Latitude: no zram yet; swap inside LUKS. MEMORY pointer for implementers. --- agent/BACKLOG.md | 63 +++++++++++++++++++++++++++++------------------- agent/MEMORY.md | 6 +++++ 2 files changed, 44 insertions(+), 25 deletions(-) diff --git a/agent/BACKLOG.md b/agent/BACKLOG.md index 499375c..6fc7ad1 100644 --- a/agent/BACKLOG.md +++ b/agent/BACKLOG.md @@ -34,24 +34,42 @@ zram on alongside for live memory pressure. Disk swap ≥ RAM for the hibernate image; zram high-priority for day-to-day swap (not sufficient alone for resume). +**Reference layout (this machine — already hibernation-capable, no zram +yet):** LUKS (`crypto_LUKS` → mapper `crypted`) holds one BTRFS with +`@swap` mounted at `/swap`; swapfile `/swap/swapfile` (here 16G); +`swapDevices = [{ device = "/swap/swapfile"; }]`; +`boot.resumeDevice = "/dev/disk/by-uuid/"`; +`boot.kernelParams = [ "resume_offset=…" ]` from +`btrfs inspect-internal map-swapfile -r`. The swapfile lives **inside +the encrypted volume** (subvolume, not a separate cleartext partition). +Installer path already sketches this (`@swap` + resume_offset patch in +`nomarchy-install` / `patch-template.py`) when `swapSize` ≥ RAM-ish. + **Scope (split before/while implementing — do not land as one mega-PR):** -1. **Design** — installer disk layout (swapfile size = RAM? partition?), - `resume`/`resume_offset`, LUKS + systemd-initrd resume, priority - (zram > disk), interaction with existing `@swap` / `swapSize` disko - path, what to do when swap was installed as `"0"`. -2. **Module** — NixOS: `zramSwap.enable`, disk swap + hibernation - (`boot.resumeDevice` / swapfile resume), menu or documented power - path for Hibernate (already in Power menu if swap works). -3. **Installer** — new installs create hibernation-capable swap by - default; document migration for existing machines (add swapfile + - rebuild). -4. **Verify** — V0/V1: eval + unit/config assertions; V2: VM resume if - feasible; **V3**: real laptop hibernate → power off → resume - (HARDWARE-QUEUE). Encrypted root is the hard case. +1. **Design** — default `swapSize` (= RAM? round up?), zram size/priority + vs disk prio, LUKS+systemd-initrd resume (already used), what when + install chose `swapSize=0`, migration for existing machines. +2. **Module** — NixOS: enable zram by default; ensure hibernation knobs + are coherent when swapfile exists (resume device/offset); Power menu + Hibernate already present — must work when swap is configured. +3. **Installer** — default new installs to hibernation-ready `@swap` + swapfile (encrypted with root); keep `0` = no swap opt-out; document + migration. +4. **Verify (required)** + - **V0:** eval / option / disko contracts. + - **V2 (mandatory, agent):** exercise hibernation in the **VM harness** + (`runNixOSTest` or install-test style) — encrypted root + BTRFS + `@swap` swapfile + resume_offset; prove hibernate→resume path at + least as far as QEMU allows (fail the item if only “config + evaluates”). Also assert zram is active with expected priority + relative to the swapfile. + - **V3:** real laptop (this LUKS+@swap layout): Hibernate → power off + → resume session; queue HARDWARE-QUEUE. zram under load is + secondary. -**Out of scope:** TLP changes; formatter. Prefer boring NixOS knobs over -custom scripts. +**Out of scope:** TLP; formatter. Prefer boring NixOS knobs; extend the +existing installer swapfile story rather than inventing a second layout. ## LATER @@ -94,13 +112,8 @@ that label is online (Gitea queues forever otherwise). pass: reformat the tree once, document in CONVENTIONS, optional CI check. **Not** the queue head — no drive-by reformats until that pass. -### Hibernation default + optional zram -**Intent:** hibernation on by default (disk swap + resume). **zram is -compatible** if disk swap remains for the hibernation image; zram only -helps *live* memory pressure (compressed RAM swap), not resume-after- -poweroff. Prefer: high-priority zram for day-to-day + lower-priority -disk swap ≥ RAM for hibernate. Design before NEXT (installer layout, -encrypted root, `resume_offset`). +### Hibernation + zram +**Promoted → NEXT #76** (2026-07-10). ## PROPOSED (agent suggestions — await human triage) @@ -182,7 +195,7 @@ decide. **Resolved** entries stay for history; agents treat them as closed. Implementation is a future/NEXT item when designed (installer + resume device + encrypted-root story). -### Still open (design, not binary yes/no) +### Still open (design detail under #76) -- **zram alongside hibernation:** compatible — see FUTURE note. Decide - default **on** (zram + disk swap) vs disk-only when hibernation ships. +- **Swap sizing / LUKS resume** — implement under NEXT #76 (disk ≥ RAM + + zram on is the product default; exact installer numbers TBD in design). diff --git a/agent/MEMORY.md b/agent/MEMORY.md index 3012978..a16de4a 100644 --- a/agent/MEMORY.md +++ b/agent/MEMORY.md @@ -30,6 +30,12 @@ iteration would otherwise rediscover. realise it): extract the logic into a pure importable file and unit-test THAT (monitor-rules.nix / checks.display-profiles is the pattern). +- **Hibernation reference (Latitude / Newton, BACKLOG #76):** LUKS whole + root BTRFS; `@swap` → `/swap`; file `/swap/swapfile`; + `boot.resumeDevice` = LUKS root UUID; `resume_offset` from + `btrfs inspect-internal map-swapfile -r`. Swap is encrypted with root + (not a cleartext partition). No zram on that box yet — zram is additive + for live pressure only. Installer already creates this when swapSize>0. - CI (`.gitea/workflows/check.yml`) is **eval-tier only** (standing decision 2026-07-10): act_runner docker-compose on the Gitea VPS; no KVM there. Full VM suite is BACKLOG **FUTURE #20**, not NEXT — needs a