diff --git a/agent/JOURNAL.md b/agent/JOURNAL.md index ccc070a..e7fafce 100644 --- a/agent/JOURNAL.md +++ b/agent/JOURNAL.md @@ -17,6 +17,23 @@ Template: --- +## 2026-07-09 — Fix Hyprland windowrule config-error banner (windowrule 0.53 migration) +- **Task:** bug tripped over while doing #45 (VM Boreal verify) — the default + desktop showed a red Hyprland config-error banner on every boot, occluding + the Waybar. +- **Did:** Root-caused via the theme-shot harness + Hyprland 0.55.4 source + (`handleWindowrule`): Hyprland 0.53 rewrote window rules — `windowrulev2` is a + hard error and the old rule-first `float, class:^…$` order no longer parses + (so the float rules weren't even applying). Migrated the 7-rule block in + `modules/home/hyprland.nix` to the new hyprlang grammar ` , + match: ^…$` (e.g. `float 1, match:class ^…$`). +- **Verified:** V0 `nix flake check --no-build` green; built the generated + `hyprland.conf` and confirmed emitted lines; **V2** theme-shot re-render — + banner gone, themed Waybar now renders (violet accent, GeistMono clock). +- **Pending:** none for the fix. A cheap `checks.*` that greps the generated + conf for the dead rule-first pattern could lock it (PROPOSED). +- **Next suggestion:** finish #45 (capture boreal preview.png), then #46. + ## 2026-07-09 — Default theme → Boreal (item #42) - **Task:** NEXT #42 — distro default theme Tokyo Night → Boreal (`VISION § B` / v1.0 bar). - **Did:** Seeded `theme-state.json` + `templates/downstream/theme-state.json` from `themes/boreal.json` (incl. border + settings). Eval fallbacks: `theme.nix` preset → boreal.json; plymouth + live ISO splash hex fallbacks; theme-shot / theme-sync examples; TESTING/RECOVERY wording. diff --git a/agent/MEMORY.md b/agent/MEMORY.md index b533d53..99902ce 100644 --- a/agent/MEMORY.md +++ b/agent/MEMORY.md @@ -103,6 +103,11 @@ iteration would otherwise rediscover. - Update order matters downstream: `sys-update` (lock) before `home-update`, or desktop changes are silently skipped against the old lock (README § 3). +- Hyprland 0.53 rewrote window rules: `windowrulev2` is a hard error and + the old rule-first `float, class:^…$` no longer parses — both surface a + red config-error banner on the default desktop. Hyprlang legacy form is + now ` , match: ^…$` (e.g. `float 1, match:class ^…$`); + effects carry a value, matchers take `match:` (§ windowrule migration). - grub `loadfont`s every `.pf2` in a theme dir — reuse a bundled DejaVu rather than shipping fonts (§ Distro branding). - The Claude Code harness drops machine-local files into the repo diff --git a/modules/home/hyprland.nix b/modules/home/hyprland.nix index 4d6b2c2..a85adbf 100644 --- a/modules/home/hyprland.nix +++ b/modules/home/hyprland.nix @@ -459,7 +459,14 @@ in # Window rules — float + center small config/utility dialogs that # tile awkwardly. Normal-priority list like `bind`/`exec-once` below, # so a downstream `windowrule = [...]` concatenates rather than - # replaces. Class regexes use `(?i)` and tolerate the XWayland + # replaces. Syntax is the post-0.53 rule rewrite (hyprlang legacy + # parser, `handleWindowrule`): each comma field is ` + # `, so effects carry a value (`float 1`, `center 1`, `size + # W H`) and matchers take a `match:` prefix (`match:class ^…$`). + # The old rule-first form (`float, class:^…$`) and the + # `windowrulev2` key are both hard errors now (red config-error + # banner on every session start — seen in the capture harness). + # Class regexes use `(?i)` and tolerate the XWayland # `.…-wrapped` binary-name form. # # Conservative set on purpose (item 41): only windows the distro @@ -468,21 +475,21 @@ in # prompt (hyprpolkitagent exposes no discoverable class) and GTK # file-chooser portals. A dead rule is harmless, but guessing a class # is worse than leaving it for a verified pass. - windowrulev2 = [ + windowrule = [ # Audio mixer (item 35): right-click the Waybar volume module. - "float, class:^(com\\.saivert\\.pwvucontrol|org\\.pulseaudio\\.pavucontrol|pavucontrol)$" - "center, class:^(com\\.saivert\\.pwvucontrol|org\\.pulseaudio\\.pavucontrol|pavucontrol)$" + "float 1, match:class ^(com\\.saivert\\.pwvucontrol|org\\.pulseaudio\\.pavucontrol|pavucontrol)$" + "center 1, match:class ^(com\\.saivert\\.pwvucontrol|org\\.pulseaudio\\.pavucontrol|pavucontrol)$" # Bluetooth manager (blueman) + CUPS printer admin. - "float, class:(?i)^(\\.?blueman-(manager|adapters)(-wrapped)?|\\.?system-config-printer(-wrapped)?)$" - "center, class:(?i)^(\\.?blueman-(manager|adapters)(-wrapped)?|\\.?system-config-printer(-wrapped)?)$" + "float 1, match:class (?i)^(\\.?blueman-(manager|adapters)(-wrapped)?|\\.?system-config-printer(-wrapped)?)$" + "center 1, match:class (?i)^(\\.?blueman-(manager|adapters)(-wrapped)?|\\.?system-config-printer(-wrapped)?)$" # Calendar popup (item 42): the Waybar clock's on-click runs # nomarchy-calendar → calcurse in a ghostty window tagged with a # distinct --class, so it floats centered instead of tiling. - "float, class:^(com\\.nomarchy\\.calendar)$" - "size 60% 65%, class:^(com\\.nomarchy\\.calendar)$" - "center, class:^(com\\.nomarchy\\.calendar)$" + "float 1, match:class ^(com\\.nomarchy\\.calendar)$" + "size 60% 65%, match:class ^(com\\.nomarchy\\.calendar)$" + "center 1, match:class ^(com\\.nomarchy\\.calendar)$" ]; # Rendered from ./keybinds.nix (the cheatsheet reads the same list),