diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 9303c04..f9c58b2 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -178,6 +178,7 @@ Pillar is **done** when every component has had a live VM pass and the roadmap c (Move items here when they land — keep them brief, link the commit/PR.) +- _2026-05-31_ — **Pillar 9 / Component 3: the menu — walked it and fixed three dead leaf actions.** Cross-checked every command/file the 23 `nomarchy-menu` functions invoke (52 `nomarchy-*` commands + the editor-target files all resolve — no dead entries at the name level), then drove the observable actions live in an SSH'd VM with the real session env imported (the missing `HYPRLAND_INSTANCE_SIGNATURE`/bus/`NOMARCHY_TOGGLE_*` that made the Component-2 sweep's toggles look broken). Working: idle/waybar/screensaver/nightlight toggles (state.json writes), gaps toggle, monitor-scaling cycle (1.6→2.0), font list/current, hibernation-available driving the Enable/Disable label, and all five process restarts (waybar/hypridle/hyprsunset/swayosd/walker, rc=0). **Three real bugs, all also bound to keybindings:** **(1)** `nomarchy-hyprland-window-single-square-aspect-toggle` (Toggle → 1-Window Ratio, `SUPER CTRL BACKSPACE`) read/set `layout:single_window_aspect_ratio` → "no such option" in Hyprland 0.52.1; the option lives under `dwindle:`. Fixed; verified it now flips `[0,0]↔[1,1]` live. **(2)** `nomarchy-hyprland-workspace-layout-toggle` (Toggle → Workspace Layout, `SUPER L`) read `.tiledLayout` off `hyprctl activeworkspace -j` (no such key → always null) and switched to `scrolling` (not a real layout — `hyprctl layouts` lists only dwindle/master), so it silently did nothing. Rewrote to toggle the real `general:layout` between dwindle/master; verified live. **(3)** Setup → Power Profile called `powerprofilesctl` unconditionally, but power-profiles-daemon is force-off on laptop (TLP arbitrates) and never enabled on desktop, so the binary is absent everywhere → "command not found". Gated the entry behind `command -v powerprofilesctl`. Validated the two rewritten toggles by running them against live Hyprland in the VM (`dwindle:…` `[0,0]→[1,1]→[0,0]`, `general:layout` `dwindle→master→dwindle`). Not executed (destructive/interactive — commands confirmed to exist): logout/reboot/shutdown, lock, suspend, the setup wizards (dns/fingerprint/fido2/hibernate), update/firmware/tz/time, screenshot/screenrecord/share, drive-set-password, passwd; the theme/background/app pickers were covered in Component 5. _Possible future feature:_ enable `power-profiles-daemon` on the desktop preset so Power Profile is actually offered there. - _2026-05-31_ — **Pillar 9 / Component 2 follow-up: grounded + fixed the three candidate bugs from the script sweep.** All three confirmed real. **(1)** `nomarchy-refresh-config` was dead on every system — it read `/etc/nixos/nomarchy/{core/home/config,features}` (the source tree never lands there; it's only at `/etc/nomarchy`, and only on VM-guest/live ISO) and fell back to `~/.local/share/nomarchy/config`, which nothing deployed even though `SKILL.md` documents it as the stock-config path. Deployed the pristine `core/home/config` tree to `~/.local/share/nomarchy/config` via `xdg.dataFile` and rewrote the script to read from there, so it works on any system without a source checkout (its only live caller, `nomarchy-refresh-fastfetch` → `fastfetch/config.jsonc`, now succeeds); fixed two stale `SKILL.md` examples that pointed at non-existent stock paths (`waybar/`, `hypr/`). Restoring arbitrary `features/`-owned configs (waybar, the full hypr tree) has no single stock mirror — deferred as a possible future feature, not grafted on. **(2)** `nomarchy-docs-scripts` shipped a stale, divergent copy in `features/scripts/utils/` (in the user `nomarchy-system-scripts` package) alongside the canonical `bin/utils/` dev tool — outside the repo it errored (`set -u` + `repo_root=…/../..`). Deleted the duplicate; grounding it surfaced **the identical bug** in `nomarchy-docs-keybindings` (a stale `features/` copy still referencing `tiling.conf` vs the canonical `tiling-v2.conf`), deleted too. Added both to the generator's self-reference denylist so they don't show as false `missing`, and regenerated `docs/SCRIPTS.md`. **(3)** Home `~/.config/nomarchy/state.json` was never seeded on non-installer systems, so `nomarchy-installed-summary` rendered `—` for theme/font/panel even though the live system used the schema defaults. Added an idempotent home-manager activation seed in `core/home/state.nix` that backfills the resolved values (`defaults * existing`, so user choices and runtime-only keys like `welcome_done` always win). Verified: `flake check` + full eval matrix clean, `refresh-config` happy/error paths and the seed deep-merge proven by hand. Activation file-write on a real boot is the one piece left for a live VM pass. - _2026-05-31_ — **Pillar 9: chasing a D-Bus error uncovered the whole app list being dropped.** A `DBus.Error … name is not activatable` seen during the menu run traced back to `notify-send` failing because mako wasn't running. Reproduced exactly via `uwsm-app -- mako` → "Command not found: mako". Root cause was far bigger than the notification daemon: `home.packages` in `features/default.nix` was wrapped in `lib.mkDefault`. `home.packages` is a list, and `filterOverrides` keeps only the highest-priority definitions — so the moment any other module set `home.packages` at normal priority (`features/scripts/default.nix`'s `[ nomarchy-scripts ]`, the installer's profile packages), the **entire curated mkDefault list was silently discarded**. Every install was missing firefox, thunar, imv, mpv, swww, **mako** (→ broken notifications), **hyprlock** (→ broken lock screen, the "hyprlock not found" flagged in the earlier script sweep), and rofi — and the drop also hid a stale `rofi-wayland` reference (merged into `rofi` upstream) that only errored once the list went live. Removed the `mkDefault` so the list merges (`home.packages` 31 → 52 pkgs) and fixed `rofi-wayland` → `rofi` (`1117dcf`). Verified on a rebuilt VM: mako installs + runs + owns `org.freedesktop.Notifications`, hyprlock/firefox present, and `nomarchy-toggle-waybar` (the command that errored) runs clean with no D-Bus error. Lesson for `docs/AGENT.md`-style guardrails: never wrap a *list/attrset* option in `lib.mkDefault` expecting downstream override — it makes the whole definition vanish when anything else contributes; `mkDefault` only makes sense on scalar leaves. diff --git a/features/scripts/utils/nomarchy-hyprland-window-single-square-aspect-toggle b/features/scripts/utils/nomarchy-hyprland-window-single-square-aspect-toggle index 410157d..0594ac4 100755 --- a/features/scripts/utils/nomarchy-hyprland-window-single-square-aspect-toggle +++ b/features/scripts/utils/nomarchy-hyprland-window-single-square-aspect-toggle @@ -1,14 +1,16 @@ #!/bin/bash set -e -# Check current single_window_aspect_ratio setting -CURRENT_VALUE=$(hyprctl getoption "layout:single_window_aspect_ratio" 2>/dev/null | head -1) +# single_window_aspect_ratio lives under the dwindle namespace (the default +# layout), not a bare `layout:` — `hyprctl getoption layout:…` returns +# "no such option" and the keyword set is silently dropped. +CURRENT_VALUE=$(hyprctl getoption "dwindle:single_window_aspect_ratio" 2>/dev/null | head -1) # Parse vec2 output: "vec2: [1, 1]" or "vec2: [0, 0]" if [[ $CURRENT_VALUE == *"[1, 1]"* ]]; then - hyprctl keyword layout:single_window_aspect_ratio "0 0" + hyprctl keyword dwindle:single_window_aspect_ratio "0 0" notify-send -u low " Disable single-window square aspect ratio" else - hyprctl keyword layout:single_window_aspect_ratio "1 1" + hyprctl keyword dwindle:single_window_aspect_ratio "1 1" notify-send -u low " Enable single-window square aspect" fi diff --git a/features/scripts/utils/nomarchy-hyprland-workspace-layout-toggle b/features/scripts/utils/nomarchy-hyprland-workspace-layout-toggle index 342895e..2070190 100755 --- a/features/scripts/utils/nomarchy-hyprland-workspace-layout-toggle +++ b/features/scripts/utils/nomarchy-hyprland-workspace-layout-toggle @@ -1,15 +1,19 @@ #!/bin/bash set -e -# Toggle the layout on the current active workspace between dwindle and scrolling +# Toggle the tiling layout between Hyprland's two built-in layouts, dwindle +# and master. (The old version read `.tiledLayout` off `hyprctl +# activeworkspace -j` and switched to "scrolling" — but that field doesn't +# exist, so the read was always null, and "scrolling" isn't a real layout +# (`hyprctl layouts` only lists dwindle/master), so the toggle silently +# did nothing.) -ACTIVE_WORKSPACE=$(hyprctl activeworkspace -j | jq -r '.id') -CURRENT_LAYOUT=$(hyprctl activeworkspace -j | jq -r '.tiledLayout') +CURRENT_LAYOUT=$(hyprctl getoption general:layout -j | jq -r '.str') case "$CURRENT_LAYOUT" in - dwindle) NEW_LAYOUT=scrolling ;; + dwindle) NEW_LAYOUT=master ;; *) NEW_LAYOUT=dwindle ;; esac -hyprctl keyword workspace $ACTIVE_WORKSPACE, layout:$NEW_LAYOUT +hyprctl keyword general:layout "$NEW_LAYOUT" notify-send -u low "󱂬 Workspace layout set to $NEW_LAYOUT" diff --git a/features/scripts/utils/nomarchy-menu b/features/scripts/utils/nomarchy-menu index abb973c..6fc1620 100755 --- a/features/scripts/utils/nomarchy-menu +++ b/features/scripts/utils/nomarchy-menu @@ -204,7 +204,13 @@ show_font_menu() { } show_setup_menu() { - local options=" Audio\n Wifi\n󰂯 Bluetooth\n󱐋 Power Profile\n System Sleep\n󰍹 Monitors" + local options=" Audio\n Wifi\n󰂯 Bluetooth" + # Power Profile drives powerprofilesctl, which only exists when + # power-profiles-daemon is running. Laptops force it off in favour of + # TLP and desktops don't enable it, so gate the entry rather than + # offer an action that dies with "command not found". + command -v powerprofilesctl >/dev/null 2>&1 && options="$options\n󱐋 Power Profile" + options="$options\n System Sleep\n󰍹 Monitors" [[ -f ~/.config/hypr/bindings.conf ]] && options="$options\n Keybindings" [[ -f ~/.config/hypr/input.conf ]] && options="$options\n Input" options="$options\n󰱔 DNS\n Security"