feat(power): re-apply battery charge limit on AC state change

The threshold was written boot-only, so a firmware that clears
charge_control_end_threshold on unplug would silently lose the cap
until the next reboot. Add a services.udev rule on the mains adapter
(ATTR{type}=="Mains", vendor-neutral) that restarts the oneshot via
systemctl --no-block on every AC state change. Uses restart (not
try-restart) so it re-applies even if the boot run was inactive.

Eval-verified: rule present when the charge limit is on, absent when
off; downstream-template-system still evaluates.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Bernardo Magri
2026-06-30 21:10:44 +01:00
parent cdfe92a089
commit 9976ea06f5
3 changed files with 29 additions and 9 deletions

View File

@@ -347,7 +347,17 @@ how to override it. Items marked ✓ are shipped.
turns it on for a `GenuineIntel` CPU.
- ✓ **longevity:** `power.batteryChargeLimit` (e.g. 80) — a backend-
independent sysfs oneshot writes `charge_control_end_threshold`. Off by
default; the installer scaffolds it commented-out on laptops.
default; the installer scaffolds it commented-out on laptops. ✓ the
threshold is now **re-applied on AC state changes** (a `services.udev`
rule on `SUBSYSTEM=="power_supply", ATTR{type}=="Mains"` restarts the
oneshot via `systemctl --no-block`), closing the firmware-resets-on-
unplug gap — the match is by adapter *type*, not kernel name
(AC/AC0/ADP1/ACAD vary), and `restart` (not `try-restart`) re-applies
even if the boot run was inactive. Eval-verified both ways (rule present
with charge limit on / absent off). **Pending an on-hardware check** (a
`sudo nixos-rebuild` + a physical unplug to fire the udev event — the
dev box has both an `AC` Mains adapter and a `BAT0`
`charge_control_end_threshold`, so it can exercise it).
- ✓ **installer:** writes `power.laptop = true` (battery probe) and
`power.thermal.enable` (Intel) into the generated `system.nix`.
- ✓ **idle cohesion:** `modules/home/idle.nix` now suspends only on
@@ -357,8 +367,6 @@ how to override it. Items marked ✓ are shipped.
logind's lid handling is left at its defaults (suspend on lid close,
ignore when docked) — an explicit "I'm done" that coheres with the
idle behaviour.
- Remaining: a boot-only→event-driven charge-limit re-apply (udev) if a
firmware resets the threshold on unplug.
- ✓ **Waybar parity:** the `custom/powerprofile` indicator now shows in the
summer-day/night whole-swap themes too. `powerProfileStatus`/`Cycle` are
named `writeShellScriptBin`s on PATH (`waybar.nix` home.packages), so the