docs(backlog): #147 was misdiagnosed — the wiring exists; the bug was pre-migration linger
All checks were successful
Check / eval (push) Successful in 4m2s

Investigated #147 and the filing was wrong in the same direction as the 321ccf7
claim: it asserted something missing that is present. The repo DOES have the
session wiring — HM's wayland.windowManager.hyprland.systemd.enable defaults on
and is line 1 of the generated hyprland.conf — and it fired correctly. Rewritten
so nobody "fixes" it by adding what is already there.

What actually happened, per systemd at 17:25:54: hyprland-session.target
stopped, StopWhenUnneeded correctly tried to take graphical-session.target with
it, and systemd REFUSED the stop — xdg-desktop-portal-gtk had a 'start' job
queued from its own post-crash restart loop, making the stop a destructive
transaction. graphical-session stayed up from the morning; hyprland-session
returned 8ms later to find it active; nothing WantedBy it was re-pulled.

None of which a Nomarchy install can reach: it needs the user manager to survive
logout, i.e. Linger=yes — and that came from an empty marker dated 2026-01-24,
PRE-DATING Bernardo's migration to Nomarchy (custom flake at the time). Nothing
here sets linger; git log -S says it was never shipped, ever. Removed via
loginctl disable-linger (no restart needed, 0 failed units after); nothing wanted
it, as nomarchy-updates.timer is Persistent=yes and catches up on login.

The item is rewritten to the class that IS real: /var/lib is machine state, a
migration reconciles the flake and leaves the rest, so Nomarchy ran six months on
its own primary V3 box with a setting it never chose and could not see. That hits
the in-flake-state promise and V3's trustworthiness at once. Pitch is now a
doctor check for drift of this class + a MIGRATION.md note — explicitly NOT
hardening the session wiring against a race a clean install cannot reach.

Also corrects #146, which claimed an ordering dependency on #147 ("fail-loops
like cliphist"). Void — cliphist's fail-loop was the same stray state. #146 has
no dependency and can be taken first; its 19-in-11-days rate was measured with
linger on and should be re-measured before a guard is built.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-16 19:13:37 +01:00
parent fe6697bd22
commit 90f0faf87b

View File

@@ -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