docs(agent): file #142 — a rebuild while docked performs an undock
All checks were successful
Check / eval (push) Successful in 3m49s

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 <internal>, 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 <noreply@anthropic.com>
This commit is contained in:
2026-07-16 09:49:49 +01:00
parent 9e64358225
commit 4a63f27bf4

View File

@@ -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 survives Waybar's actual environment, so the next hand-written jsonc can
reintroduce it silently. 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 <internal>, 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 45).
**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 ### 120. A netinstall ISO, next to the fat offline one
Bernardo 2026-07-14, after seeing the measured size: **keep the current ISO Bernardo 2026-07-14, after seeing the measured size: **keep the current ISO