feat(display): blackout rescue — re-enable a disabled panel on undock
Some checks failed
Check / eval (push) Failing after 1m40s

Bernardo's question: with "Laptop screen off" active, does the panel
come back when the dock is yanked? VM answer (new maintainer harness
tools/monitor-fallback.nix, softGL desktop): no — Hyprland 0.55.4
leaves the session with zero active outputs and never re-enables a
soft-disabled monitor. rescue_blackout in the display hotplug watcher
now re-enables every disabled output (immediate, retried, idempotent
keyword + toast) whenever a monitorremoved leaves nothing active;
independent of the profile auto-switch and its settings gate.

Sharp edge documented rather than hidden: the zero-output state itself
crashes Hyprland in the VM ~4/5 runs (aquamarine CBackend::dispatchIdle
ABRT within ~0.5s — faster than any userland rescue; a control run
removing the external with the panel ACTIVE survives 5/5, so the state
is the trigger, not headless removal; crash reproduced with the rescue
provably inert, so not caused by it). Rescue ships as defense-in-depth:
it recovers every surviving case, and the worst case on real DRM is
session-to-greeter on a re-lit panel instead of a black brick. Rider
fix: `grep -c .` exits 1 at count zero — the ||-guard on that pipeline
silently disabled the rescue exactly when it mattered.

Verified: hazard V2 (VM reproduces the dead state); control
discriminator 5/5; flake check green. V3 pending: real-dock
undock-while-off in HARDWARE-QUEUE (run with nothing important open;
crash on real DRM = rework the row to mirror or wait for a Hyprland
bump).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-12 18:09:17 +01:00
parent 6439105d38
commit c840202018
6 changed files with 208 additions and 2 deletions

View File

@@ -424,6 +424,25 @@ Design/decision records and a running log of shipped work (items marked
(`swapactiveworkspaces`, exactly-2 gate); Audio gains a self-gated
"Send output → <dock sink>" quick row (the watcher's manual override).
Real-dock V3 for both in HARDWARE-QUEUE.
✓ **Undock blackout rescue (2026-07-12):** Bernardo asked whether the
panel comes back if you undock while "Laptop screen off" — VM answer
(tools/monitor-fallback.nix, full softGL desktop): **no**, Hyprland
0.55.4 leaves zero active outputs and never re-enables a soft-disabled
monitor. Fix: `rescue_blackout` in the display hotplug watcher
(hyprland.nix) — on monitorremoved with zero active outputs,
immediately (and with retries) `keyword monitor <name>,preferred,auto,
auto` every disabled output + toast; independent of the profile
auto-switch gate (safety invariant, not a preference). Sharp edge
found while testing: the zero-output state itself crashes Hyprland in
the VM ~4/5 runs (ABRT in aquamarine CBackend::dispatchIdle, ~0.5s —
faster than any userland rescue; control run with the panel active
survives 5/5, so it's the state, not headless removal; monitor-
disconnect crashes are a known upstream class). Posture: rescue ships
as defense-in-depth (recovers every surviving case; worst case on real
DRM is session-to-greeter on the re-lit panel, not a black brick);
V3 decides if the menu row needs a mirror-based rework. Also fixed in
the rescue: `grep -c .` exits 1 at count 0 — an `||`-guard on that
pipeline silently disabled the rescue exactly when it mattered.
✓ **neon-glass finish (#88, `VISION § D`):** rewrote whole-swap
`rofi.rasi` to rofi-native `@color` glass panel (cyan rim, soft
selection wash — same hex-alpha glass pattern as Boreal); btop title/

View File

@@ -105,6 +105,11 @@ unattended env it uses is in the script, and the same flow works
interactively from the live terminal. If the desktop comes up unthemed,
read `/var/log/nomarchy-hm-preactivate.log` on the installed system.
Two full-desktop VM harnesses (softGL Hyprland, too heavy for `checks.*`)
live next to the scripts: `tools/theme-shot.nix` (themed-desktop
screenshots) and `tools/monitor-fallback.nix` (undock blackout rescue —
disabled panel must re-enable when the last active output disappears).
## 5. VM-specific gotchas
- **No KVM** (e.g. nested without acceleration): everything works but