feat(displays): display profiles — docked/undocked switching (item 15a)
All checks were successful
Check / eval (push) Successful in 3m4s

nomarchy.displayProfiles: named layouts for the same outputs, each a
list of nomarchy.monitors-style entries. The active profile lives in
the in-flake state (settings.displayProfile) on the night-light
pattern: nomarchy-display-profile apply <name> fires the baked hyprctl
rules instantly and writes the state with --no-switch; the next rebuild
bakes the profile's entries over nomarchy.monitors whole-by-name.
Monitor-rule composition is extracted to pure monitor-rules.nix
(renderer + 3-layer resolve, incl. a disable-guard so a stale menu
resolution pick can't resurrect a profile-disabled panel, and junk
state degrading to base config instead of an eval error) — because a
writeText/toFile state fixture is unreadable at flake-check eval time,
the new checks.display-profiles unit-tests the pure function directly.
Menu: System › Display gains a self-gated "Profiles ›" row (●/○ active
mark, Base layout to clear); commented template example + README row.

Verified: V0 (flake check, forcing the new check's asserts); V1 — a
scratch downstream through lib.mkFlake builds: the generated tool
passes bash -n with correct rules (disable/vrr/float scale), the baked
hyprland.conf shows the exact expected overlay, the menu renders, and
list/usage smoke-test clean. Remains: V3 live switching on a dock
(HARDWARE-QUEUE). Slices b (hotplug auto-switch) + c (workspace
binding) stay in item 15.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Bernardo Magri
2026-07-05 17:52:19 +01:00
parent e02b4d8200
commit 9df18261f9
11 changed files with 271 additions and 43 deletions

View File

@@ -17,6 +17,32 @@ Template:
---
## 2026-07-05 — display profiles slice a (iteration #28, item 15a)
- **Task:** BACKLOG NEXT#15 slice a, per the #27 design: option +
overlay + applier + menu + template example.
- **Did:** nomarchy.displayProfiles (attrsOf (listOf monitorType));
monitor logic extracted to pure modules/home/monitor-rules.nix
(rule renderer + 3-layer resolve: profile replaces whole-by-name →
resolution picks field-level with the disable-guard → wildcard),
hyprland.nix consumes it and gains nomarchy-display-profile
(list/active/apply/base; apply = baked hyprctl rules + state write
--no-switch, base = clear + hyprctl reload) on PATH only when
profiles exist; menu: Display gains a gated "Profiles " row + new
display-profile mode (●/○ active mark, Base layout row); template
example + README row. checks.display-profiles unit-tests resolve
(incl. junk-state degradation) — the first HM-eval fixture attempt
hit "path not valid" (eval store won't realise writeText/toFile
under flake check), hence the pure-function extraction.
- **Verified:** V0 (check's asserts force at eval); V1 — scratch
downstream through lib.mkFlake builds: tool bash -n + correct baked
rules (disable, vrr, floats), hyprland.conf shows the exact overlay
(wildcard + kept base + disabled panel + profile output), menu bash
-n, list/usage smoke. Live switching needs a session+dock → V3.
- **Pending:** V3 queued. Slices b (hotplug auto-switch) and c
(workspace binding) remain in the item.
- **Next suggestion:** #16 greeter theming, or 15b if momentum on
displays is preferred.
## 2026-07-05 — display-profiles design pass (iteration #27, item 15, no code)
- **Task:** BACKLOG NEXT#15 — the entry itself demands "design first,
write the plan into this entry before coding". Backlog-only iteration.