diff --git a/agent/BACKLOG.md b/agent/BACKLOG.md index 540d1ee..0a1bc3f 100644 --- a/agent/BACKLOG.md +++ b/agent/BACKLOG.md @@ -186,42 +186,86 @@ but it is not cosmetic either: a silently dead hypridle means **no auto-lock** idle suspend. Cost: systemd can't see it — `WatchdogSec` needs `sd_notify` hypridle doesn't implement, and the process never exits — so detection has to be external: a guard watching for the `CRITICAL` line, or a liveness probe on its -Wayland fd, then `systemctl --user restart hypridle`. **Sequence it after #147**: -today's disconnect was the compositor dying, and restarting hypridle into a dead -compositor just fail-loops into `start-limit-hit` exactly as cliphist does. The -trigger is still unknown — *not* dock/undock (no display-watch activity in the -3 min before any of them) and *not* a D-Bus quota disconnect (no broker errors). +Wayland fd, then `systemctl --user restart hypridle`. + +**Correction 2026-07-16:** this entry originally said "sequence it after #147, +because restarting hypridle into a dead compositor fail-loops into +`start-limit-hit` exactly as cliphist does". **That reasoning is void** — #147 +turned out not to be a distro bug at all (it needed stray pre-migration linger, +since removed), and cliphist's fail-loop was a symptom of that same stray state. +There is no ordering constraint: **#146 stands on its own and can be taken +first.** The underlying caution survives in weaker form and is still worth +designing for — a guard must not restart hypridle into a session whose +compositor is gone — but that is ordinary care in the guard, not a dependency +on another item. + +The trigger is still unknown — *not* dock/undock (no display-watch activity in +the 3 min before any of them) and *not* a D-Bus quota disconnect (no broker +errors). **Note the 19-in-11-days figure was measured on a box with linger on**; +whether the rate holds now that the user manager is torn down at logout is +itself unknown, and re-measuring is the cheap first step before building a guard. Worth a reproducer + an upstream comment on #171: it has sat ten months on vaxerski's "that will cause a segfault no?", and we have better data than the reporter did. -### 147. A re-login leaves the session's user units dead, and nothing brings them back +### 147. Nomarchy cannot see machine state it never set — and it bit the QA box for 6 months -Bernardo, 2026-07-16: after re-logging in, Waybar took 5+ seconds and -nomarchy-doctor reported cliphist, network-manager-applet and udiskie failing. -Root cause is the session lifecycle, not those apps. Hyprland exited at -17:25:39 and the replacement came up at **17:25:52** — a 13-second gap — but -`graphical-session.target` never re-entered (its `ActiveEnterTimestamp` still -read 08:03:32, from the *morning's* session). So: units with a restart policy -burn their start limit inside that gap against a Wayland socket that does not -exist yet (cliphist's journal is explicit — `wl-paste: Failed to connect to a -Wayland server`, 5 restarts in one second, `start-limit-hit` at 17:25:40, -twelve seconds before the new compositor existed); units without one -(nm-applet, udiskie) simply die once and stay dead forever. Nothing re-enters -the target, so nothing recovers. +**Rewritten 2026-07-16 after diagnosis; the original filing was wrong and its +wrongness is the point.** It claimed "a re-login leaves session units dead; +the repo never adopted the standard session wiring". The repo *has* the wiring +— HM's `wayland.windowManager.hyprland.systemd.enable` defaults on and is line +1 of the generated `hyprland.conf` — and it fired correctly. Do not go add it. -We have already paid for this once without naming it: `modules/home/hyprland.nix` -launches Waybar from `exec-once` rather than a unit, and the comment there says -why — "bound to graphical-session.target the unit raced Hyprland's IPC on -relogin". That is this bug, worked around for one service; the 5-second Waybar -start is the workaround being slow instead of failing. Fix is the standard -wiring the repo never adopted: the compositor imports `WAYLAND_DISPLAY` + -`HYPRLAND_INSTANCE_SIGNATURE` into the user manager and starts/stops a -`hyprland-session.target` on entry/exit (Home Manager's -`wayland.windowManager.hyprland.systemd.enable`, or uwsm). Cost: touches how -every session service is bound, so it wants a VM pass and a real relogin on -hardware — but it would let Waybar go back to being a unit and unblock #144's -guard. +**What actually happened**, from systemd's own words at the 17:25:54 relogin: + +``` +Stopped target Hyprland compositor session. +Requested transaction contradicts existing jobs: Transaction for +graphical-session.target/stop is destructive (xdg-desktop-portal-gtk.service +has 'start' job queued, but 'stop' is included in transaction). +graphical-session.target: Failed to enqueue stop job, ignoring +Reached target Hyprland compositor session. +``` + +`hyprland-session.target` stopped; `StopWhenUnneeded=yes` correctly tried to +take `graphical-session.target` with it; systemd **refused the stop** because +portal-gtk had a `start` job queued from its own post-crash restart loop (3 +restart/fail lines in that 13s gap). So graphical-session never went down, 8ms +later hyprland-session came back to find it active, and nothing `WantedBy` it +was re-pulled. cliphist had already burned 5 restarts into `start-limit-hit`; +nm-applet/udiskie have no restart policy and just stayed dead. + +**But none of that can happen on a Nomarchy install.** The whole sequence needs +the user manager to survive logout, i.e. `Linger=yes` — and linger came from an +empty marker in `/var/lib/systemd/linger/bernardo` dated **2026-01-24**, which +**pre-dates Bernardo's migration to Nomarchy** (he was on a custom flake then). +Nothing here sets it: not modules, not hosts, not templates, and `git log -S` +says it was never shipped, ever. Removed 2026-07-16 (`loginctl disable-linger`, +no restart needed); nothing wanted it — `nomarchy-updates.timer` is +`Persistent=yes` and catches up on login. + +**So the real item is the class, not the bug.** `/var/lib` is machine state; a +migration reconciles the flake and leaves everything else exactly as it was. +Nomarchy therefore ran for six months on its own primary V3 box with a setting +it never chose, never set, and could not see — on the machine whose whole job is +telling us how the distro behaves. That is a direct hit on the in-flake-state +promise (state outside the checkout) *and* on V3's trustworthiness: a QA box +that silently diverges reports on a distro nobody ships. + +**Pitch:** a `nomarchy-doctor` check for drift of this class — linger is the +worked example (`loginctl show-user $USER -p Linger` vs. what the flake asks +for), and MIGRATION.md should say plainly that `/var/lib` survives and what to +sweep. Cost is small and it is the only part of this worth shipping. **Do not** +harden the session wiring against the portal-gtk race: a clean install cannot +reach it, and defending against it would be clever code for a state we do not +ship. + +**Loose thread for whoever takes this:** `modules/home/hyprland.nix` runs Waybar +from `exec-once` rather than a unit because the unit "raced Hyprland's IPC on a +**warm** relogin ... never retried, so the bar vanished" — and a warm relogin is +exactly what linger creates. That workaround may now be defending against +nothing. Do not rip it out on this note alone; it works, and the claim needs a +real relogin without linger to test. ### 120. A netinstall ISO, next to the fat offline one