docs(backlog): #147 was misdiagnosed — the wiring exists; the bug was pre-migration linger
All checks were successful
Check / eval (push) Successful in 4m2s
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:
104
agent/BACKLOG.md
104
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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user