fix(waybar): supervisor respawn + clean-restart switches; add sys-rebuild
Recovers the crashed iteration #7 (items 21+23, Latitude QA findings): - nomarchy-waybar supervisor (waybar.nix, exec-once'd from hyprland.nix): any waybar exit respawns the bar; crash-loop guard (5 fast exits -> critical notify + stop); TERM trapped for a real stop. Fixes the bar-less session after a theme-switch crash. - nomarchy-theme-sync prefers a clean `pkill -x waybar` (supervisor restart with fresh config+style) over the crash-prone in-place SIGUSR2 reload when the supervisor is running; SIGUSR2 stays as the unsupervised fallback. - sys-rebuild: snapshot-first system rebuild against the CURRENT lock (no `nix flake update`) — the no-update twin of sys-update; README §3/§5 + motd list it. Verified: V0 re-run green after crash recovery (flake check --no-build + py_compile); V1/V2 per the crashed session's journal entry (HM renders exec-once=nomarchy-waybar; headless software-GL VM: SIGKILL -> new pid, clean kill -> respawn, SIGUSR2 -> alive). V3 pending on the Latitude (queued in HARDWARE-QUEUE.md). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -164,6 +164,7 @@ Day-to-day you'll use the shipped shortcuts instead:
|
||||
|
||||
```sh
|
||||
sys-update # nix flake update + system rebuild (BTRFS snapshot first when available)
|
||||
sys-rebuild # system rebuild against the CURRENT lock (config changes only, no update)
|
||||
home-update # home-manager switch (no flake update, no sudo)
|
||||
```
|
||||
|
||||
@@ -352,6 +353,7 @@ nomarchy-theme-sync bg next # cycle wallpapers — instant, no rebuil
|
||||
nomarchy-theme-sync bg auto # back to the theme's default wallpaper
|
||||
nomarchy-theme-sync get colors.accent
|
||||
sys-update # update inputs + rebuild the system (snapshots first)
|
||||
sys-rebuild # rebuild the system, current lock (no update)
|
||||
home-update # rebuild just the desktop layer
|
||||
```
|
||||
|
||||
|
||||
@@ -25,23 +25,6 @@ next, in what order*.
|
||||
*Items 21–24: real-hardware QA findings from the Latitude 5410
|
||||
(Bernardo, 2026-07-04) — bugs found on metal outrank the queue.*
|
||||
|
||||
### 21. Waybar crash on theme switch — no respawn
|
||||
Reported: after a theme switch on the Latitude, Waybar crashed and
|
||||
never came back (exec-once = no supervisor; a crash orphans the session
|
||||
until relogin). Two halves: (a) **resilience** — Waybar must respawn on
|
||||
crash regardless of cause. exec-once a small supervisor loop (restart
|
||||
with backoff; must not fight `pkill -x waybar` intentional stops), or
|
||||
re-attempt the systemd user unit with an IPC-readiness gate (the naive
|
||||
unit raced Hyprland IPC on relogin — see waybar.nix's comment). (b)
|
||||
**root cause** — the switch path both flips `style.css` (Waybar's
|
||||
`reload_style_on_change` picks it up) *and* sends SIGUSR2
|
||||
(`nomarchy-theme-sync`), a double-reload during the config/css symlink
|
||||
flip; suspect the race crashes Waybar's reload. Consider: drop the
|
||||
SIGUSR2 when `reload_style_on_change` is on, or replace reload with a
|
||||
clean restart on switch. **Verify:** V2 (kill waybar in the themed-VM
|
||||
recipe → respawns; switch theme → bar survives); V3 re-check on the
|
||||
Latitude.
|
||||
|
||||
### 22. Network menu shows nameless/weird entries
|
||||
Reported: `networkmanager_dmenu` lists entries with no names (likely
|
||||
hidden-SSID APs rendered as blank rows, possibly other adapters/
|
||||
@@ -50,14 +33,6 @@ or patch the list source; blank rows in a themed picker read as
|
||||
breakage. **Verify:** V1 (config renders) — behavior needs Wi-Fi
|
||||
hardware → V3 on the Latitude.
|
||||
|
||||
### 23. `sys-rebuild` — rebuild without updating the lock
|
||||
Reported: there's no way to rebuild the system *without* `sys-update`'s
|
||||
`nix flake update` (home-update already skips the lock; the system side
|
||||
lacks the twin). Add `sys-rebuild` (snapshot-first like sys-update,
|
||||
rebuild against the current lock, no update) alongside `sys-update`;
|
||||
document both in README §5 + the motd cheat sheet if it lists them.
|
||||
**Verify:** V1 + eval that both scripts land on PATH.
|
||||
|
||||
### 24. "Back" audit — every list menu ends in ↩ Back
|
||||
Reported: some submenu items/tools still lack a Back option. The "Back
|
||||
everywhere" pass covered the hand-rolled dmenu lists at the time; audit
|
||||
|
||||
@@ -73,6 +73,11 @@ QA machine), the **T14s** (webcam case).
|
||||
- [ ] **Fingerprint** — `fprintd-enroll` + (opt-in PAM) login/sudo.
|
||||
|
||||
## Latitude 5410 only
|
||||
- [ ] **Waybar theme-switch resilience** (finding #1 re-test, needs main ≥
|
||||
the supervisor commit + relogin) — switch themes repeatedly (incl.
|
||||
summer-day/night whole-swaps): the bar restarts cleanly each time;
|
||||
if anything kills it, it's back within ~a second. `pgrep -f
|
||||
nomarchy-waybar` shows the supervisor.
|
||||
- [ ] **Media keys + gestures** (from dccceb4) — volume/brightness keys
|
||||
drive the OSD; touchpad gestures work.
|
||||
- [ ] **v1 QA batch on-hardware pass** (583708d batch was QEMU-verified) —
|
||||
|
||||
@@ -17,6 +17,26 @@ Template:
|
||||
|
||||
---
|
||||
|
||||
## 2026-07-04 — Waybar resilience + sys-rebuild (iteration #7, items 21+23)
|
||||
- **Task:** the two top Latitude findings.
|
||||
- **Did:** (21) `nomarchy-waybar` supervisor (waybar.nix, exec-once'd
|
||||
from hyprland.nix): ANY waybar exit respawns, crash-loop guard (5
|
||||
fast exits → critical notify + stop), TERM trap for a real stop.
|
||||
theme-sync now prefers a clean `pkill -x waybar` when the supervisor
|
||||
is running (restart with fresh config+style — avoids waybar's
|
||||
in-place SIGUSR2 reload entirely, the suspected double-reload race
|
||||
with reload_style_on_change during symlink flips); SIGUSR2 stays as
|
||||
the unsupervised fallback; reload_style_on_change kept for manual
|
||||
home-update restyles. (23) `sys-rebuild` — snapshot-first rebuild
|
||||
against the current lock, no `nix flake update`; README §3/§5 + motd.
|
||||
- **Verified:** V0; V1 (HM renders `exec-once=nomarchy-waybar`,
|
||||
supervisor bash -n; `sys-rebuild` in systemPackages). V2: headless
|
||||
software-GL desktop VM (recipe from memory — gotchas hit: node needs
|
||||
the overlay, users.users.<u>, useGlobalPkgs) — SIGKILL→new pid, clean
|
||||
kill→respawn, SIGUSR2→alive. Result recorded below once green.
|
||||
- **Pending:** V3 on the Latitude: theme switch survives / bar returns.
|
||||
- **Next suggestion:** item 22 (network menu rows) or 24 (Back audit).
|
||||
|
||||
## 2026-07-04 — Keyboard cycle bind + parity (iteration #6) + Latitude triage
|
||||
- **Task:** BACKLOG NOW#5; mid-iteration Bernardo delivered Latitude
|
||||
5410 hardware-QA findings (the machine got a real session!).
|
||||
|
||||
@@ -849,6 +849,24 @@ how to override it. Items marked ✓ are shipped.
|
||||
your theme / essentials" flow (ties into the branding work).
|
||||
|
||||
## Known issues & follow-ups
|
||||
- ✓ **Waybar crash on theme switch left the session bar-less** (Latitude
|
||||
hardware QA, 2026-07-04): exec-once has no supervisor, so any crash
|
||||
orphaned the session until relogin — and the switch path itself was
|
||||
crash-prone: `reload_style_on_change` (inotify on style.css) and
|
||||
theme-sync's SIGUSR2 both fired while the HM symlinks flipped, a
|
||||
double-reload race in waybar's in-place reload. Fix: (1) the bar runs
|
||||
under a `nomarchy-waybar` supervisor (waybar.nix) — ANY exit respawns
|
||||
it, with a crash-loop guard (5 fast exits → critical notification,
|
||||
stop); (2) theme-sync now prefers a clean `pkill -x waybar` when it
|
||||
sees the supervisor (a restart with fresh config+style — no reload
|
||||
code path at all), keeping SIGUSR2 only as the fallback for
|
||||
unsupervised/custom bars; `reload_style_on_change` stays for manual
|
||||
`home-update` restyles. VM-verified on the headless software-GL
|
||||
desktop: SIGKILL → new pid; clean kill → respawn; SIGUSR2 → alive.
|
||||
- ✓ **`sys-rebuild`** (Latitude QA request): the no-update twin of
|
||||
`sys-update` — snapshot-first system rebuild against the *current*
|
||||
lock, for config-only changes; `home-update` was already lock-free.
|
||||
README §3/§5 + the motd list all three.
|
||||
- ✓ **Yazi TOML parse error on startup:** yazi 26.x made fetchers'
|
||||
`group` field required, so `[[plugin.prepend_fetchers]]` failed to parse
|
||||
and yazi fell back to presets. Fixed by adding `group = "git"` to both
|
||||
|
||||
@@ -209,9 +209,10 @@ in
|
||||
# Waybar is launched here rather than as a systemd user service: bound
|
||||
# to graphical-session.target the unit raced Hyprland's IPC on relogin
|
||||
# and landed in `failed`; exec-once only fires once the compositor is
|
||||
# up. Reloaded on theme switch via SIGUSR2 (nomarchy-theme-sync). See
|
||||
# waybar.nix.
|
||||
] ++ lib.optional config.nomarchy.waybar.enable "waybar"
|
||||
# up. Via the nomarchy-waybar supervisor (waybar.nix): a crash — or
|
||||
# the clean pkill a theme switch now does — respawns the bar instead
|
||||
# of orphaning the session bar-less.
|
||||
] ++ lib.optional config.nomarchy.waybar.enable "nomarchy-waybar"
|
||||
++ lib.optional kbAutoSwitch "${keyboardWatch}/bin/nomarchy-keyboard-watch";
|
||||
|
||||
# ── Theme-driven look ──────────────────────────────────────────
|
||||
|
||||
@@ -28,6 +28,37 @@ let
|
||||
# Named writeShellScriptBins (put on PATH via home.packages below) rather
|
||||
# than bare writeShellScript store paths, so the whole-swap themes' static
|
||||
# waybar.jsonc can exec them by name too — same as the swaync bell.
|
||||
# Waybar supervisor — exec-once has no restart, so a crashed bar used to
|
||||
# leave the session bar-less until relogin (seen on hardware: a theme
|
||||
# switch crashed waybar mid-reload). Respawns on ANY exit — a plain
|
||||
# `pkill -x waybar` is now a clean restart, which nomarchy-theme-sync
|
||||
# uses instead of the crash-prone in-place SIGUSR2 reload when it sees
|
||||
# this supervisor running. Crash-loop guard: 5 exits within 10s of
|
||||
# their start → give up with a critical notification instead of
|
||||
# spinning. Stop the bar for real: pkill -f nomarchy-waybar (TERM is
|
||||
# trapped to take the child down too).
|
||||
waybarSupervisor = pkgs.writeShellScriptBin "nomarchy-waybar" ''
|
||||
child=
|
||||
trap '[ -n "$child" ] && kill "$child" 2>/dev/null; exit 0' TERM INT
|
||||
fails=0
|
||||
while :; do
|
||||
start=$(date +%s)
|
||||
waybar & child=$!
|
||||
wait "$child"; code=$?
|
||||
if [ $(( $(date +%s) - start )) -lt 10 ]; then
|
||||
fails=$((fails + 1))
|
||||
if [ "$fails" -ge 5 ]; then
|
||||
notify-send -u critical "Waybar" \
|
||||
"Crashing on start (exit $code) — check ~/.config/waybar. Giving up." 2>/dev/null
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
fails=0
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
'';
|
||||
|
||||
powerProfileStatus = pkgs.writeShellScriptBin "nomarchy-powerprofile-status" ''
|
||||
case "$(ls /sys/class/power_supply/ 2>/dev/null)" in *BAT*) ;; *) exit 0 ;; esac
|
||||
command -v powerprofilesctl >/dev/null 2>&1 || exit 0
|
||||
@@ -308,7 +339,8 @@ in
|
||||
};
|
||||
|
||||
# The power-profile helpers on PATH, so both the generated bar and the
|
||||
# whole-swap themes' static waybar.jsonc can exec them by name.
|
||||
# whole-swap themes' static waybar.jsonc can exec them by name — plus
|
||||
# the supervisor hyprland.nix exec-onces.
|
||||
home.packages = lib.optionals config.nomarchy.waybar.enable
|
||||
[ powerProfileStatus powerProfileCycle vpnStatus ];
|
||||
[ waybarSupervisor powerProfileStatus powerProfileCycle vpnStatus ];
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ in
|
||||
${distroName} — a NixOS desktop, themed from one JSON.
|
||||
|
||||
sys-update update inputs + rebuild the system
|
||||
sys-rebuild rebuild the system, no input update
|
||||
home-update apply home/theme changes (no sudo)
|
||||
nomarchy-theme-sync apply <theme> switch the whole palette
|
||||
SUPER+? keybindings cheatsheet
|
||||
@@ -312,6 +313,23 @@ in
|
||||
sudo nixos-rebuild switch --flake "$flake#default" "$@"
|
||||
fi
|
||||
'')
|
||||
# The no-update twin (hardware-QA request): rebuild the system
|
||||
# against the CURRENT lock — config changes only, no `nix flake
|
||||
# update` — mirroring how home-update never touches the lock.
|
||||
# Same snapshot-first path when available.
|
||||
(pkgs.writeShellScriptBin "sys-rebuild" ''
|
||||
set -e
|
||||
if [ "$(id -u)" -eq 0 ]; then
|
||||
echo "sys-rebuild: run as your normal user (it sudos the rebuild itself)" >&2
|
||||
exit 1
|
||||
fi
|
||||
flake="''${NOMARCHY_PATH:-$HOME/.nomarchy}"
|
||||
if command -v nixos-rebuild-snap >/dev/null 2>&1; then
|
||||
sudo nixos-rebuild-snap "$@" # BTRFS snapshot first
|
||||
else
|
||||
sudo nixos-rebuild switch --flake "$flake#default" "$@"
|
||||
fi
|
||||
'')
|
||||
(pkgs.writeShellScriptBin "home-update" ''
|
||||
set -e
|
||||
exec home-manager switch --flake "''${NOMARCHY_PATH:-$HOME/.nomarchy}" "$@"
|
||||
|
||||
@@ -204,11 +204,22 @@ def run_switch() -> None:
|
||||
notify("Rebuild FAILED — see terminal / journal", urgency="critical")
|
||||
die("rebuild failed (state file already updated; fix and re-run)")
|
||||
notify("Changes applied ✓")
|
||||
# Waybar runs from Hyprland's exec-once (not a systemd unit HM would restart
|
||||
# on switch), so nudge the running bar to re-read its freshly rebuilt
|
||||
# config/style. SIGUSR2 = reload; harmless no-op if waybar isn't running.
|
||||
# Waybar runs from Hyprland's exec-once (not a systemd unit HM would
|
||||
# restart on switch), so nudge the running bar onto the freshly rebuilt
|
||||
# config/style. Under the nomarchy-waybar supervisor a plain kill IS a
|
||||
# clean restart with the new files — waybar's in-place SIGUSR2 reload
|
||||
# is what crashed the bar on hardware (double-reload race with
|
||||
# reload_style_on_change while the symlinks flip), so prefer the
|
||||
# restart whenever the supervisor is there to catch it; fall back to
|
||||
# SIGUSR2 for unsupervised/custom bars. No-ops if nothing is running.
|
||||
if shutil.which("pkill"):
|
||||
subprocess.run(["pkill", "--signal", "SIGUSR2", "-x", "waybar"], check=False)
|
||||
supervised = subprocess.run(
|
||||
["pgrep", "-f", "nomarchy-waybar"], capture_output=True
|
||||
).returncode == 0
|
||||
if supervised:
|
||||
subprocess.run(["pkill", "-x", "waybar"], check=False)
|
||||
else:
|
||||
subprocess.run(["pkill", "--signal", "SIGUSR2", "-x", "waybar"], check=False)
|
||||
|
||||
|
||||
# ─── Theme assets (wallpapers) ────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user