From 4a63f27bf47d64c1ff870f4907ae90906e14e792 Mon Sep 17 00:00:00 2001 From: Bernardo Magri Date: Thu, 16 Jul 2026 09:49:49 +0100 Subject: [PATCH] =?UTF-8?q?docs(agent):=20file=20#142=20=E2=80=94=20a=20re?= =?UTF-8?q?build=20while=20docked=20performs=20an=20undock?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bernardo: every rebuild while docked re-lights the panel and throws a workspace onto it; he re-picks Dock mode by hand. Static diagnosis, three steps, each already proven by our own code: - dock mode is runtime-only (`keyword monitor , disable`, hyprland.nix:205) and absent from state.json — the one display setting outside the in-flake state; - the config's only monitor line is the catch-all `,preferred,auto,1`, so a reload re-enables every output. The undock path already uses `hyprctl reload` AS the hammer that re-enables a disabled panel (hardware-proven 2026-07-14) — so a rebuild performs an undock by construction; - reconcile diffs `monitors all`, which lists disabled monitors, so the set is unchanged across the flip and the watcher never sees it. Blind spot of round 4/5's "the output set is the truth". Notes the trap: baking the disable into the config is a zero-output session at login (the #100/#127 brick). Persist intent, re-assert from the watcher, gate on an external being present. Co-Authored-By: Claude Opus 4.8 --- agent/BACKLOG.md | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/agent/BACKLOG.md b/agent/BACKLOG.md index 3f3d476..2117ceb 100644 --- a/agent/BACKLOG.md +++ b/agent/BACKLOG.md @@ -271,6 +271,53 @@ bug, not the instance: nothing today asserts that a whole-swap's on-click survives Waybar's actual environment, so the next hand-written jsonc can reintroduce it silently. +### 142. A rebuild while docked undoes dock mode (the panel comes back, a workspace jumps to it) + +Bernardo 2026-07-16: every rebuild while docked lands in the undocked state — +laptop panel back on, a workspace moved onto it — and he re-picks **Dock mode** +in the Display menu by hand. Diagnosed statically on the dev box (no session +disruption needed; our own code already proves each step): + +1. **Dock mode is runtime-only.** `nomarchy-display-transition dock` ends with + `hyprctl keyword monitor , disable` (`hyprland.nix:205`) — a live + compositor command. Nothing writes it down: his `state.json` has no display + key at all, so dock mode is the one display setting outside the in-flake + state, which is exactly why it cannot survive anything. +2. **Any config reload re-enables everything.** The generated config's only + monitor line is the catch-all `monitor=,preferred,auto,1` (live + hyprland.conf:175 — he has no `displayProfiles`), so a reload turns every + output back on, `eDP-1` included, and Hyprland puts a workspace on the + output that just appeared. We do not have to guess that a reload does this: + the **undock** path uses `hyprctl reload` deliberately, as the hammer that + re-enables an inert disabled panel, hardware-proven 2026-07-14 + (`hyprland.nix:225`). A rebuild reloads the config and therefore *performs + an undock*, precisely and by construction. +3. **The watcher cannot see it happen.** `reconcile` diffs `outputs()` = + `hyprctl monitors all` (`:505`), which lists **disabled** monitors too. So + the connected set is byte-identical before and after the flip, `cur != + known_outputs` is false, and reconcile returns having done nothing. The + watcher tracks connect/disconnect and is structurally blind to + enable/disable — the blind spot in round 4/5's "the output set, not the + event, is the truth" (ROADMAP § Docking rounds 4–5). + +**Shape, and the trap in the obvious fix.** The tempting move is to bake the +disable into the config (state → `monitor=eDP-1,disable`) so a reload preserves +it. **Do not** without a guard: a persisted disable with no external attached +is a zero-output session at login — the black brick #100 and #127 are both +about. The config is evaluated with no knowledge of what is plugged in, so it +must keep defaulting to "everything on". Better: persist the *intent* +(`settings.display.dockMode`, in-flake, menu-writable — the philosophy this +currently violates) and let the **watcher** re-assert it, since only it knows +what is live. That needs reconcile to also track the *enabled* set, so +"internal came back on while an external is present and the state says docked" +becomes an event it can act on — which fixes the reload case and any other +path that silently re-enables the panel. Gate re-assertion on an external +actually being present, never on the state key alone. + +Pass = docked, `nomarchy-home` (and `nomarchy-rebuild`) → panel stays off, no +workspace moves, no menu trip; undocked rebuild unchanged; unplug while the +state says docked still restores the panel. + ### 120. A netinstall ISO, next to the fat offline one Bernardo 2026-07-14, after seeing the measured size: **keep the current ISO