fix(display): #142 — dock mode is an intent, and survives a rebuild
All checks were successful
Check / eval (push) Successful in 3m48s
All checks were successful
Check / eval (push) Successful in 3m48s
Every rebuild while docked re-lit the panel and threw a workspace onto it. Not forgetfulness: a rebuild PERFORMS an undock. Dock mode lived only in the compositor (`keyword monitor <internal>, disable`, nothing written down), the config's only monitor line is the catch-all `monitor=,preferred,auto,1`, and rewriting the config makes Hyprland reload it — re-enabling every output. Our own undock path already uses `hyprctl reload` as exactly that hammer (hardware-proven 2026-07-14). The watcher could not rescue it: reconcile diffs `monitors all`, which lists disabled outputs, so the connected set is identical across the flip — structurally blind, the blind spot of rounds 4-5's "the output set is the truth". So the intent is recorded where every other setting lives — settings.display.dockMode, in-flake, menu-writable — written at the one choke point both menu and watcher pass through (transition: dock → true, undock → false, `enable` of an internal → false, because "Screen on" IS leaving dock mode and must not be undone a second later). The watcher re-asserts it as a tick invariant rather than an event reaction, which is what makes the reload case work; auto_dock was already idempotent, so it costs one `hyprctl monitors` per tick. The trap avoided: baking the disable into the config would survive a reload and hand a user with no external a zero-output session at login — the #100/#127 brick. The config cannot know what is plugged in, so it keeps defaulting to "everything on" and the re-assert is gated on an external being present. Verified: 9/9 gates unit-tested by driving the REAL generated function against stubs (incl. no-external → never re-dock, profile active → yield, already-docked → no churn), plus the state write/read round-trip on a throwaway checkout so the live flake was untouched. V3 queued — needs a relogin, the watcher is exec-once. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -509,6 +509,22 @@ Everything else below stays open; order is convenience, not a gate.
|
||||
active and PPD switching governors; opt-ins: ROCm (`rocminfo`, a GPU
|
||||
PyTorch/Ollama smoke) and the XDNA NPU driver loading.
|
||||
- [ ] **Fingerprint** — `fprintd-enroll` + (opt-in PAM) login/sudo.
|
||||
- [ ] **#142 dock mode survives a rebuild** — **relogin first** (the watcher is
|
||||
`exec-once`; `nomarchy-home` alone leaves the old one running and you
|
||||
would be testing nothing — round 6's lesson). Then, docked: run
|
||||
`nomarchy-home`. Pass = the laptop panel stays off, no workspace lands on
|
||||
it, no menu trip; `journalctl --user -t nomarchy-display-watch` shows
|
||||
`dock-intent=true panel=eDP-1 state=re-enabled action=re-dock` (a rebuild
|
||||
re-lights the panel and the watcher takes it back within ~1s, so a brief
|
||||
flicker is expected — the panel staying *up* is the failure).
|
||||
Then the three gates that must NOT fire, since this code can disable a
|
||||
panel: (a) Menu ▸ Display ▸ **Screen on** → the panel stays on (intent
|
||||
cleared; if it snaps off again within a second, that is the bug);
|
||||
(b) **undock** → panel returns and stays; (c) boot/relogin **undocked**
|
||||
with `settings.display.dockMode` still `true` in state.json → panel stays
|
||||
on (no external ⇒ never re-dock). (c) is the one that matters: it is the
|
||||
#127 brick if it is wrong. Gates are unit-tested against stubs, but only
|
||||
hardware proves the wiring.
|
||||
- [ ] **#138 dock audio does not break a running browser** — the plug event
|
||||
itself is the only thing V2 could not do (the tool was driven by hand;
|
||||
Hyprland calls the same entry point). **Relogin first** — the watcher is
|
||||
|
||||
Reference in New Issue
Block a user