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:
@@ -449,6 +449,36 @@ Design/decision records and a running log of shipped work (items marked
|
||||
(#131). Those windows therefore carry float/center rules and deliberately no
|
||||
`size` rule. Measured after: calendar 1536×936 = exactly 60%×65%, doctor
|
||||
1408×1008 = 55%×70%, both centred in the Waybar work area.
|
||||
- ✓ **Dock mode survives a rebuild (#142, 2026-07-16):** Bernardo: every rebuild
|
||||
while docked re-lit the laptop panel and threw a workspace onto it, and he
|
||||
re-picked Dock mode by hand. It was not forgetfulness — **a rebuild performed
|
||||
an undock, by construction**. Dock mode existed only inside the compositor
|
||||
(`keyword monitor <internal>, disable`, nothing written down), the generated
|
||||
config's only monitor line is the catch-all `monitor=,preferred,auto,1`, and a
|
||||
rewritten config makes Hyprland reload — which re-enables every output. We did
|
||||
not have to theorise that: the **undock** path already uses `hyprctl reload`
|
||||
as precisely that hammer, hardware-proven 2026-07-14. And the watcher could
|
||||
not rescue it, because `reconcile` diffs `monitors all`, which lists disabled
|
||||
outputs too — so the connected set is identical across the flip and the
|
||||
watcher is structurally blind to it (the blind spot of rounds 4–5's "the
|
||||
output set, not the event, is the truth").
|
||||
Fix: dock mode is an **intent** now, recorded where every other setting lives
|
||||
— `settings.display.dockMode`, in-flake and menu-writable — written at the one
|
||||
choke point both the menu and the watcher pass through
|
||||
(`nomarchy-display-transition`: dock → true, undock → false, and `enable` of
|
||||
an internal → false, since "Screen on" *is* leaving dock mode and must not be
|
||||
undone a second later). The watcher then re-asserts it as a **tick invariant**
|
||||
rather than an event reaction, which is what makes the reload case work at
|
||||
all; `auto_dock` was already idempotent (it returns early unless the panel is
|
||||
up), so the cost is one `hyprctl monitors` per tick.
|
||||
**The trap avoided** was baking the disable into the config (state →
|
||||
`monitor=eDP-1,disable`), which would survive a reload beautifully and, with
|
||||
no external attached, hand the user a zero-output session at login — the black
|
||||
brick of #100/#127. The config cannot know what is plugged in, so it keeps
|
||||
defaulting to "everything on" and the re-assert is gated on an external
|
||||
actually being present. Verified by unit-testing the real generated function
|
||||
against stubs — 9/9, including *no external → never re-dock* — plus the state
|
||||
write/read round-trip on a throwaway checkout.
|
||||
- ✓ **MIGRATION.md: Mozilla `profiles.ini` (#144, 2026-07-16):** a real
|
||||
migration ate Bernardo's `~/.thunderbird/profiles.ini`, so Thunderbird did
|
||||
what it does on any new machine — made an empty profile and opened it —
|
||||
|
||||
Reference in New Issue
Block a user