aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--todo.org114
2 files changed, 61 insertions, 56 deletions
diff --git a/.gitignore b/.gitignore
index 6a3c13d..d08398a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,3 +23,6 @@ dotfiles/common/.claude/commands/
# Python bytecode cache
__pycache__/
+
+# Dated local backups of secret files (kept on disk, never tracked)
+*.bak-[0-9]*
diff --git a/todo.org b/todo.org
index a2c106d..9b60d9d 100644
--- a/todo.org
+++ b/todo.org
@@ -13,68 +13,14 @@ Four levels, matching the Emacs config (=org-highest-priority ?A=, =org-lowest-p
Rule of thumb: A = dated-and-must; B = the active backlog; C = parking lot; D = untriaged. Fixing the undated A/B tasks means either dating them or demoting to C.
* Archsetup Open Work
-** DONE [#B] toggle key for touchpad on/off
-CLOSED: [2026-05-20 Wed]
-*** 2026-05-20 Wed @ 18:18:30 -0400 Spec: touchpad toggle + waybar indicator
-
-**** Current state
-A toggle mechanism already exists in the live home dir but is only partly committed.
-- =~/.local/bin/toggle-touchpad= (live, NOT in repo): reads/writes a state file at =${XDG_RUNTIME_DIR:-/tmp}/touchpad-state= (values "enabled"/"disabled"), flips =hyprctl keyword "device[$TOUCHPAD]:enabled" true|false=, and fires a =notify info "Touchpad" ...= toast. Hardcodes =TOUCHPAD="pixa3854:00-093a:0274-touchpad"=.
-- =~/.local/bin/touchpad-auto= (live, NOT in repo): daemon watching Hyprland's =.socket2.sock= for mouseadded/mouseremoved/configreloaded, auto-disables the touchpad when an external mouse is present, writes the same state file. Same hardcoded device name.
-- Keybinding already committed: =bind = $mod, F9, exec, toggle-touchpad= (=hyprland.conf:315=).
-- State file confirmed live at =/run/user/1000/touchpad-state= (reads "enabled").
-
-**** Gap
-1. No waybar indicator — nothing in modules-right shows touchpad state; no =custom/touchpad= module exists.
-2. Neither =toggle-touchpad= nor =touchpad-auto= is committed into the repo. They live only in =~/.local/bin=, so a fresh stow won't install them. They belong in =dotfiles/hyprland/.local/bin/= (the =dotfiles/dwm/.local/bin/toggle-touchpad= is the old X11/xinput version, unrelated).
-3. =touchpad-auto= is never started — no =exec-once= launches it.
-4. The toggle doesn't refresh waybar, so an indicator would lag until its poll interval.
-
-**** Proposed implementation
-1. New status script =dotfiles/hyprland/.local/bin/waybar-touchpad= mirroring =waybar-layout= / =waybar-netspeed= (emit one JSON line: text + tooltip + class). Reads the state file the toggle already writes — single source of truth, no extra hyprctl call. Emits a "disabled" class + off-icon when the state file reads "disabled", else "enabled" + on-icon.
-2. Waybar module in =dotfiles/hyprland/.config/waybar/config=, using "signal" so the toggle pushes an instant refresh (no polling — state only changes on toggle or mouse hotplug):
- =, "custom/touchpad": { "exec": "waybar-touchpad", "return-type": "json", "signal": 9, "on-click": "toggle-touchpad" }=
- Add =custom/touchpad= to modules-right, near =idle_inhibitor=.
-3. Refresh-on-toggle: have =toggle-touchpad= (and =touchpad-auto='s set function) run =pkill -RTMIN+9 waybar= after each write to the state file (RTMIN+N ⇄ waybar "signal": N). Alternative: drop "signal", use "interval": 2 (simpler, ~2s lag, constant poll). Signal is the cleaner fit.
-4. =style.css= (=dotfiles/hyprland/.config/waybar/style.css=): add =#custom-touchpad= to the shared padding/hover selector lists; add =#custom-touchpad.disabled { color: #d47c59; }= (the dupre orange already used for warnings). Enabled state inherits the default color.
-5. Keybinding: keep =$mod+F9= (=hyprland.conf:315=). The waybar on-click gives a mouse path to the same action.
-6. Commit the live scripts so stow installs them: =toggle-touchpad= and =touchpad-auto= into =dotfiles/hyprland/.local/bin/= (plus the =pkill= line), and =waybar-touchpad= (new). If the auto-disable-on-external-mouse behavior is wanted at boot, add =exec-once = touchpad-auto= near the other daemon exec-once lines.
-
-**** Decisions (Craig, 2026-05-20)
-1. Icons: 󰍽 enabled / 󰍾 disabled (the mouse / mouse-off pair).
-2. Waybar on-click toggles the touchpad.
-3. Commit =touchpad-auto= and add its =exec-once= so it runs at login.
-4. Signal-driven refresh (=pkill -RTMIN+9 waybar=).
-Note: the hardcoded device name =pixa3854:00-093a:0274-touchpad= is Framework-laptop-specific — a portability concern for other machines, not a blocker for this task.
-
-*** 2026-05-20 Wed @ 18:29:06 -0400 Implemented the toggle + waybar indicator (in repo)
-Built per spec + decisions above. Committed the two formerly-live-only scripts into the repo and added the indicator:
-- =dotfiles/hyprland/.local/bin/waybar-touchpad= (new) — reads =$XDG_RUNTIME_DIR/touchpad-state=, emits JSON (text/tooltip/class), fail-safe to "enabled". Unit-tested in =tests/waybar-touchpad/= (6 Normal/Boundary cases).
-- =dotfiles/hyprland/.local/bin/toggle-touchpad= — copied from =~/.local/bin=, added =pkill -RTMIN+9 waybar= so the indicator refreshes on toggle.
-- =dotfiles/hyprland/.local/bin/touchpad-auto= — copied in, =pkill -RTMIN+9 waybar= inside =set_touchpad= so auto on/off events refresh too. Added =exec-once = touchpad-auto= to =hyprland.conf=.
-- =waybar/config= — =custom/touchpad= module (signal:9, on-click toggle-touchpad), placed in modules-right before idle_inhibitor.
-- =waybar/style.css= — =#custom-touchpad= in padding + hover lists; =.disabled { color: #d47c59 }= (dupre orange).
-- =$mod+F9= bind already present (=hyprland.conf=), left as-is.
-
-*** 2026-05-20 Wed @ 18:36:26 -0400 Deployed + verified on velox
-Discovered =.local/bin= is stow-symlinked (waybar-layout/netspeed point into the repo); the two touchpad scripts were real files only because they weren't committed. Replaced both real files with repo symlinks and symlinked the new =waybar-touchpad= (matching the existing relative-symlink form). velox needed no hyprland.conf change — =exec-once = touchpad-auto= and the =$mod+F9= bind were already present. waybar =config= / =style.css= are real local files on velox (config diverges: standalone battery, no sysmonitor group), so applied targeted edits there rather than a copy.
-
-Verified end-to-end after a waybar restart: config loads with no parse errors; toggle round-trips state enabled → disabled (󰍾, class disabled) → enabled (󰍽), and the =pkill -RTMIN+9 waybar= refresh fires into the running bar. Touchpad left enabled. Visual confirmation (icon in bar, orange when off) is Craig's to eyeball. Other machines (ratio) pick this up on =git pull && make restow hyprland= — their =.local/bin= and waybar configs are symlinks, so no real-file conflict there.
-** DONE [#B] Airplane-mode toggle + waybar indicator
-CLOSED: [2026-05-21 Thu]
-Laptop-only low-power toggle, modeled on the touchpad indicator. Wifi off (bluetooth left alone for earbuds), CPU EPP → power, brightness → 35%, and stops network-only services. Disengage restores only what it recorded, so anything already off stays off.
-*** 2026-05-21 Thu @ 17:43:07 -0400 Built the toggle, indicator, and tests
-- =dotfiles/hyprland/.local/bin/airplane-mode= (new) — toggle. Engage records prior state (wifi enabled/disabled, EPP value, brightness, which services were active) to =$XDG_RUNTIME_DIR/airplane-state=, then applies low-power: =nmcli radio wifi off=, EPP → power on all CPUs (sudo sysfs write), =brightnessctl set 35%=, and stops Tier 1+2 services (tailscaled, proton.VPN, avahi-daemon, cups, wsdd, geoclue, sshd, fail2ban + user syncthing). Disengage replays the recorded state — only re-enables wifi if it was on, only restarts services it stopped. Refreshes the bar via =pkill -RTMIN+10 waybar=.
-- =dotfiles/hyprland/.local/bin/waybar-airplane= (new) — indicator. Reads =mode= from the state file; fail-safe to inactive. Laptop-gated: exits silently (module hidden) when no battery is present (=/sys/class/power_supply/BAT*=). One clear plane glyph (FA U+F072) for both states; color carries state (gold active / gray inactive).
-- =waybar/config= — =custom/airplane= module (signal 10, on-click airplane-mode), placed after custom/touchpad. =waybar/style.css= — =#custom-airplane= in padding + hover lists; =.active { color: #d7af5f }= (dupre gold).
-- Tests: =tests/airplane-mode/= (20 — engage/disengage/preserve-existing-state/dispatch, via command stubs + fake EPP sysfs) and =tests/waybar-airplane/= (10 — states/boundary/laptop-gating). All green; shellcheck clean.
-- Deployed + live-verified on velox (engage → disengage round-trip works). Other machines pick it up via git pull && make restow hyprland.
** TODO [#C] Waybar indicators unevenly spaced
The right-side module icons don't sit at even intervals — spacing reads as inconsistent across the group. Tune the per-module margin/padding in =dotfiles/hyprland/.config/waybar/style.css= so the icons are evenly distributed. Noticed 2026-05-21 after adding the airplane indicator.
** TODO [#C] Airplane-mode toggle robustness follow-ups
Two minor robustness gaps in =dotfiles/hyprland/.local/bin/airplane-mode= surfaced when the feature shipped (2026-05-21). Neither is a live bug — both are defense-in-depth.
- No laptop guard on the toggle itself. The =waybar-airplane= indicator hides on battery-less machines, but =airplane-mode= would still run if invoked directly (e.g. a future keybind on a desktop). Mirror the =is_laptop= check at the top of the toggle so it no-ops off a laptop.
- Brightness-restore edge. If =brightnessctl get= returns empty at engage time, disengage skips the restore (guarded by =[ -n "$bright_was" ]=) and the screen stays at 35%. Fall back to a sane brightness (e.g. 100%) when no prior value was recorded.
+** TODO [#C] Wlogout exit-menu buttons are rectangular, not square
+The wlogout exit menu renders its buttons taller than they are wide, so the cells read as vertical rectangles instead of squares. Fix the button sizing in the wlogout style (=dotfiles/hyprland/.config/wlogout/style.css=) so each cell is square. Noticed 2026-05-21. Related: the [#D] VERIFY about wlogout sizing across displays.
** DOING [#A] Separate dotfiles from archsetup
*** 2026-05-11 Mon @ 13:01:29 -0500 AI Response: Dotfile separation plan
Approach: keep =dotfiles/= committed in this repo as the working default (Craig's machines and CI keep functioning untouched), but make the *source location* a config variable. The install script learns one new conf key — =DOTFILES_REPO= / =DOTFILES_BRANCH= — and when set, clones that repo into =~/.dotfiles= and stows from there instead of from =dotfiles/= inside archsetup. The Makefile gets a =DOTFILES= override env var so the same stow targets work whether dotfiles live in-repo or elsewhere. No submodule (adds fragility for a curl|bash installer); a separate published =archsetup-dotfiles= repo is optional follow-up, not a blocker.
@@ -750,3 +696,59 @@ The 2026-05-11 VM test run shows it installs cleanly in a fresh install (=...ins
CLOSED: [2026-05-11 Mon]
The 2026-05-11 VM test aborted because =validate_hyprland_plugins= in =scripts/testing/lib/validation.sh= checked for =~/.local/bin/hyprland-plugins-setup=, which was deliberately removed in dd543e3 (=feat(hyprland): remove plugins, add layout cycling=; Hyprland 0.54 brings the layouts into core). The function's =return 1= under run-test.sh's =set -e= killed the run before the test report was written or the VM cleaned up.
Fix: deleted =validate_hyprland_plugins= and =validate_hyprpm_hook= (the hyprpm pacman hook was removed in the same commit) plus their calls in =validate_window_manager=; disabled errexit in =run-test.sh= from the validation phase onward so a failed check is counted (=VALIDATION_FAILED=) instead of fatal — the script signals pass/fail via its exit code at the end. Verified with =bash -n=; the next =make test= run confirms the count-not-abort behavior.
+** DONE [#B] toggle key for touchpad on/off
+CLOSED: [2026-05-20 Wed]
+*** 2026-05-20 Wed @ 18:18:30 -0400 Spec: touchpad toggle + waybar indicator
+
+**** Current state
+A toggle mechanism already exists in the live home dir but is only partly committed.
+- =~/.local/bin/toggle-touchpad= (live, NOT in repo): reads/writes a state file at =${XDG_RUNTIME_DIR:-/tmp}/touchpad-state= (values "enabled"/"disabled"), flips =hyprctl keyword "device[$TOUCHPAD]:enabled" true|false=, and fires a =notify info "Touchpad" ...= toast. Hardcodes =TOUCHPAD="pixa3854:00-093a:0274-touchpad"=.
+- =~/.local/bin/touchpad-auto= (live, NOT in repo): daemon watching Hyprland's =.socket2.sock= for mouseadded/mouseremoved/configreloaded, auto-disables the touchpad when an external mouse is present, writes the same state file. Same hardcoded device name.
+- Keybinding already committed: =bind = $mod, F9, exec, toggle-touchpad= (=hyprland.conf:315=).
+- State file confirmed live at =/run/user/1000/touchpad-state= (reads "enabled").
+
+**** Gap
+1. No waybar indicator — nothing in modules-right shows touchpad state; no =custom/touchpad= module exists.
+2. Neither =toggle-touchpad= nor =touchpad-auto= is committed into the repo. They live only in =~/.local/bin=, so a fresh stow won't install them. They belong in =dotfiles/hyprland/.local/bin/= (the =dotfiles/dwm/.local/bin/toggle-touchpad= is the old X11/xinput version, unrelated).
+3. =touchpad-auto= is never started — no =exec-once= launches it.
+4. The toggle doesn't refresh waybar, so an indicator would lag until its poll interval.
+
+**** Proposed implementation
+1. New status script =dotfiles/hyprland/.local/bin/waybar-touchpad= mirroring =waybar-layout= / =waybar-netspeed= (emit one JSON line: text + tooltip + class). Reads the state file the toggle already writes — single source of truth, no extra hyprctl call. Emits a "disabled" class + off-icon when the state file reads "disabled", else "enabled" + on-icon.
+2. Waybar module in =dotfiles/hyprland/.config/waybar/config=, using "signal" so the toggle pushes an instant refresh (no polling — state only changes on toggle or mouse hotplug):
+ =, "custom/touchpad": { "exec": "waybar-touchpad", "return-type": "json", "signal": 9, "on-click": "toggle-touchpad" }=
+ Add =custom/touchpad= to modules-right, near =idle_inhibitor=.
+3. Refresh-on-toggle: have =toggle-touchpad= (and =touchpad-auto='s set function) run =pkill -RTMIN+9 waybar= after each write to the state file (RTMIN+N ⇄ waybar "signal": N). Alternative: drop "signal", use "interval": 2 (simpler, ~2s lag, constant poll). Signal is the cleaner fit.
+4. =style.css= (=dotfiles/hyprland/.config/waybar/style.css=): add =#custom-touchpad= to the shared padding/hover selector lists; add =#custom-touchpad.disabled { color: #d47c59; }= (the dupre orange already used for warnings). Enabled state inherits the default color.
+5. Keybinding: keep =$mod+F9= (=hyprland.conf:315=). The waybar on-click gives a mouse path to the same action.
+6. Commit the live scripts so stow installs them: =toggle-touchpad= and =touchpad-auto= into =dotfiles/hyprland/.local/bin/= (plus the =pkill= line), and =waybar-touchpad= (new). If the auto-disable-on-external-mouse behavior is wanted at boot, add =exec-once = touchpad-auto= near the other daemon exec-once lines.
+
+**** Decisions (Craig, 2026-05-20)
+1. Icons: 󰍽 enabled / 󰍾 disabled (the mouse / mouse-off pair).
+2. Waybar on-click toggles the touchpad.
+3. Commit =touchpad-auto= and add its =exec-once= so it runs at login.
+4. Signal-driven refresh (=pkill -RTMIN+9 waybar=).
+Note: the hardcoded device name =pixa3854:00-093a:0274-touchpad= is Framework-laptop-specific — a portability concern for other machines, not a blocker for this task.
+
+*** 2026-05-20 Wed @ 18:29:06 -0400 Implemented the toggle + waybar indicator (in repo)
+Built per spec + decisions above. Committed the two formerly-live-only scripts into the repo and added the indicator:
+- =dotfiles/hyprland/.local/bin/waybar-touchpad= (new) — reads =$XDG_RUNTIME_DIR/touchpad-state=, emits JSON (text/tooltip/class), fail-safe to "enabled". Unit-tested in =tests/waybar-touchpad/= (6 Normal/Boundary cases).
+- =dotfiles/hyprland/.local/bin/toggle-touchpad= — copied from =~/.local/bin=, added =pkill -RTMIN+9 waybar= so the indicator refreshes on toggle.
+- =dotfiles/hyprland/.local/bin/touchpad-auto= — copied in, =pkill -RTMIN+9 waybar= inside =set_touchpad= so auto on/off events refresh too. Added =exec-once = touchpad-auto= to =hyprland.conf=.
+- =waybar/config= — =custom/touchpad= module (signal:9, on-click toggle-touchpad), placed in modules-right before idle_inhibitor.
+- =waybar/style.css= — =#custom-touchpad= in padding + hover lists; =.disabled { color: #d47c59 }= (dupre orange).
+- =$mod+F9= bind already present (=hyprland.conf=), left as-is.
+
+*** 2026-05-20 Wed @ 18:36:26 -0400 Deployed + verified on velox
+Discovered =.local/bin= is stow-symlinked (waybar-layout/netspeed point into the repo); the two touchpad scripts were real files only because they weren't committed. Replaced both real files with repo symlinks and symlinked the new =waybar-touchpad= (matching the existing relative-symlink form). velox needed no hyprland.conf change — =exec-once = touchpad-auto= and the =$mod+F9= bind were already present. waybar =config= / =style.css= are real local files on velox (config diverges: standalone battery, no sysmonitor group), so applied targeted edits there rather than a copy.
+
+Verified end-to-end after a waybar restart: config loads with no parse errors; toggle round-trips state enabled → disabled (󰍾, class disabled) → enabled (󰍽), and the =pkill -RTMIN+9 waybar= refresh fires into the running bar. Touchpad left enabled. Visual confirmation (icon in bar, orange when off) is Craig's to eyeball. Other machines (ratio) pick this up on =git pull && make restow hyprland= — their =.local/bin= and waybar configs are symlinks, so no real-file conflict there.
+** DONE [#B] Airplane-mode toggle + waybar indicator
+CLOSED: [2026-05-21 Thu]
+Laptop-only low-power toggle, modeled on the touchpad indicator. Wifi off (bluetooth left alone for earbuds), CPU EPP → power, brightness → 35%, and stops network-only services. Disengage restores only what it recorded, so anything already off stays off.
+*** 2026-05-21 Thu @ 17:43:07 -0400 Built the toggle, indicator, and tests
+- =dotfiles/hyprland/.local/bin/airplane-mode= (new) — toggle. Engage records prior state (wifi enabled/disabled, EPP value, brightness, which services were active) to =$XDG_RUNTIME_DIR/airplane-state=, then applies low-power: =nmcli radio wifi off=, EPP → power on all CPUs (sudo sysfs write), =brightnessctl set 35%=, and stops Tier 1+2 services (tailscaled, proton.VPN, avahi-daemon, cups, wsdd, geoclue, sshd, fail2ban + user syncthing). Disengage replays the recorded state — only re-enables wifi if it was on, only restarts services it stopped. Refreshes the bar via =pkill -RTMIN+10 waybar=.
+- =dotfiles/hyprland/.local/bin/waybar-airplane= (new) — indicator. Reads =mode= from the state file; fail-safe to inactive. Laptop-gated: exits silently (module hidden) when no battery is present (=/sys/class/power_supply/BAT*=). One clear plane glyph (FA U+F072) for both states; color carries state (gold active / gray inactive).
+- =waybar/config= — =custom/airplane= module (signal 10, on-click airplane-mode), placed after custom/touchpad. =waybar/style.css= — =#custom-airplane= in padding + hover lists; =.active { color: #d7af5f }= (dupre gold).
+- Tests: =tests/airplane-mode/= (20 — engage/disengage/preserve-existing-state/dispatch, via command stubs + fake EPP sysfs) and =tests/waybar-airplane/= (10 — states/boundary/laptop-gating). All green; shellcheck clean.
+- Deployed + live-verified on velox (engage → disengage round-trip works). Other machines pick it up via git pull && make restow hyprland.