From 4563af6702bcc44defbca22baeb87ab8261572c6 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Thu, 9 Jul 2026 06:43:19 -0500 Subject: chore(todo): archive completed and cancelled tasks --- archive/task-archive.org | 177 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) (limited to 'archive') diff --git a/archive/task-archive.org b/archive/task-archive.org index 17804c0..662dd0f 100644 --- a/archive/task-archive.org +++ b/archive/task-archive.org @@ -695,3 +695,180 @@ CLOSED: [2026-06-27 Sat] From the roam inbox (2026-06-24): the "idle inhibitor" name doesn't work as a mnemonic — something like "sleep" (i.e. "keep awake" / "no-sleep") would land better. Decide the new name, then rename across the touchpoints: the =custom/idle= waybar module, the keybind mnemonic, and the backing script names (=hypridle-toggle= / =waybar-idle= from the 2026-06-24 idle-inhibitor work). Needs Craig's call on the name first, so not solo. Renamed to "caffeine" (Craig's call, 2026-06-27): =custom/caffeine= module, =waybar-caffeine= + =caffeine-toggle= scripts, tooltip "Caffeine: ON/OFF", CSS + test suites updated. Keybind stays =$mod+I= (=$mod+C= is hyprpicker). Shipped in dotfiles 8b45b51. +** DONE [#B] Guard against live mesa/hyprland/wayland-runtime updates :hyprland: +CLOSED: [2026-06-28 Sun] +:PROPERTIES: +:LAST_REVIEWED: 2026-06-09 +:END: +A live =pacman -Syu= that swaps mesa/hyprland/wayland runtime libs out from under a running Hyprland session can crash the compositor: the next GPU-lib call hits a now-"(deleted)" library and SIGABRTs, taking the Wayland clients down with it. Hit ratio 2026-06-07 (mesa 26.0.6 -> 26.1.2 + hyprland upgraded live; Hyprland SIGABRT took down awww/insync/emacs). Likely the driver behind ratio's high lifetime unsafe-shutdown ratio — a crashed compositor forces a hard reset. + +Shipped as a pacman PreTransaction hook rather than a wrapper, so it fires no matter how the upgrade is launched (pacman, yay, topgrade). =scripts/hypr-live-update-guard= aborts the transaction before any package is swapped when the GPU/compositor runtime set is being upgraded AND Hyprland is running, pointing the user to re-run from a TTY with the session stopped; it stays quiet when Hyprland isn't running (the safe from-a-TTY path). Override via =HYPR_ALLOW_LIVE_UPDATE=1= or by touching the sentinel file named in the abort message. archsetup installs the script to =/usr/local/bin= and the hook to =/etc/pacman.d/hooks/= in the hyprland path. Decision logic unit-tested (=tests/hypr-live-update-guard=, 9 cases). Live firing test filed under Manual testing and validation. Commits: archsetup (this session). +** DONE [#B] ZFS pre-pacman snapshot installer step (ZFS-root) :feature:zfs: +CLOSED: [2026-06-30 Tue] +Add a ZFS-root-gated installer step that installs the pre-pacman snapshot pacman hook plus a self-pruning =/usr/local/bin/zfs-pre-snapshot= (KEEP=10). The script is hand-placed on velox, not authored by archsetup, so a reinstall loses it; snapshots accumulated unbounded (53 since April) because nothing prunes them and Sanoid ignores non-autosnap_ names. Gate to ZFS-root (velox; ratio is btrfs). Also correct the stale 2026-01-17 security-doc line claiming it's "already in install-archzfs". Needs the hook file (source from velox) and a ZFS-root VM test. + +Shipped: =configure_pre_pacman_snapshots()= in boot_ux (late, ZFS-gated) + =scripts/zfs-pre-snapshot=; unit tests for pruning + a Testinfra assertion. VM-verified ZFS install passed 97/0 (test_zfs_pre_pacman_snapshot_hook PASSED). The "stale doc" turned out accurate (it's an install-archzfs archive) — left as-is. Design notes and the KEEP=10 script: [[file:docs/design/2026-06-29-zfs-pre-snapshot-installer.org]]. Origin: home handoff 2026-06-29. +** DONE [#B] Waybar timer module :waybar: +CLOSED: [2026-06-29 Mon] +:PROPERTIES: +:LAST_REVIEWED: 2026-05-26 +:END: +Shipped as =wtimer= in the dotfiles repo (=134d61e=), a single always-visible module right of the battery/resource readout, non-collapsible. Covers all four modes (timer / alarm / stopwatch / pomodoro) with multiple running at once: the bar shows the most urgent item with a per-type glyph + "+N" badge, the tooltip lists them all. Left-click creates (fuzzel), middle-click pauses, right-click cancels, scroll cycles the primary; notify fires on completion and pomodoro phase changes. Pure-functions-over-injected-clock design; CLI serializes state with flock + atomic write so the 1s render and click handlers never lose an update or double-fire. TDD: 86 cases, 95% line coverage. Design spec: [[file:docs/design/2026-06-29-waybar-timer-module-spec.org][docs/design/2026-06-29-waybar-timer-module-spec.org]]. Live-verified on velox (glyph renders, position, countdown); the color states + click interactions filed under Manual testing and validation. + +A custom waybar module providing three time-keeping functions, surfaced in the bar with click/scroll controls and dunst notifications on completion. + +- *Alarm* — fire a notification at a wall-clock time (e.g. 2:00pm). Builds on the existing =notify= + =at= pattern from protocols.org. +- *Timer* — count down a duration (e.g. 25m) and notify when it elapses. +- *Pomodoro* — alternating work/break cycles (default 25/5, long break after 4) with the bar showing phase + remaining time. + +Implementation notes (to flesh out when picked up): waybar =custom= module(s) with =exec= polling or a persistent =exec= script emitting JSON; click actions to start/pause/reset; a small state file under =~/.local/state= or =~/.local/var=. Lives in the hyprland tier (=dotfiles/hyprland/.config/waybar/= + a backing script in =hyprland/.local/bin/=). TDD the backing script per testing.md. + +*** 2026-06-24 Wed @ 17:32:37 -0400 Scope expansion from roam capture (folded duplicate) +A roam-inbox capture asked for the same widget and expands the scope, so folding it in here rather than duplicating: +- *One panel, mode-selectable* — a single component where you choose timer / stopwatch / alarm; the icon changes to reflect the selected mode. +- *Stopwatch* — a count-up (the third function alongside the alarm/timer/pomodoro above), hover shows start time ("Stopwatch started: 12:22pm"). +- Hover text per mode: timer "Timer: 5 min", alarm "Alarm: 12:15pm", stopwatch "Stopwatch started: 12:22pm". +- *Multiple simultaneous* — several timers/alarms/stopwatches set and displayed at once, in one panel. +- Deliverable includes proposing a few panel designs and recommending one before building. +** DONE [#B] Sysmon module right-click cycles the visible metric :feature:waybar:solo: +CLOSED: [2026-06-28 Sun] +Shipped in the dotfiles repo (=f7b6896=, implemented from this archsetup session per Craig). =waybar-sysmon= reads a selected metric from =$XDG_RUNTIME_DIR/waybar/sysmon-metric= (absent = host default, so the old behavior is preserved); the new =sysmon-cycle= helper advances through a host-appropriate ring (battery only on a laptop), wraps, and refreshes waybar via signal 12 wired to =on-click-right=. Left-click stays the btop popup. Added cpu/temp/mem icons + thresholds. TDD: 13 new =waybar-sysmon= selection cases + a 9-case =sysmon-cycle= suite, full dotfiles suite green (29 suites). =sysmon-cycle= symlinked into =~/.local/bin= on velox. Live visual/relogin check filed under "Manual testing and validation". Handoff sent to the dotfiles inbox. +Builds on the just-shipped =custom/sysmon= collapse (dotfiles be7469b). Right-clicking the module rotates which metric is the visible one, in a fixed order: battery → cpu → temp → mem → disk → back to battery. Each click advances one step and wraps around. The host default (battery on a laptop, disk on a desktop) is the starting/reset metric; the tooltip keeps showing all metrics regardless. Left-click stays =pypr toggle monitor= (the btop popup) — the cycle lives on =on-click-right=. + +Implementation notes: =waybar-sysmon= needs a persisted selection (a state file in =$XDG_RUNTIME_DIR/waybar/=, absent = host default) that it reads to pick the visible metric. A new =sysmon-cycle= helper bumps the index and signals the module to refresh (add a =signal= to =custom/sysmon=, like the other custom modules; wire =sysmon-cycle= to =on-click-right=). TDD both — extend =tests/waybar-sysmon= for selection-driven output, add a =tests/sysmon-cycle= for the index advance/wrap and the signal. +** DONE [#B] Network module: enterprise WiFi add/edit deferred to vNext :waybar:network: +CLOSED: [2026-06-29 Mon] +Decided 2026-06-29 (Craig): keep v1 to open + WPA-PSK add/edit; the +WPA-Enterprise / 802.1X add/edit form is vNext, not a v1 phase. v1 still +*activates* any saved enterprise profile and points editing at nmtui/nmcli. +Evidence that settled it: 24 saved profiles on velox, 18 WPA-PSK, 0 enterprise — +no 802.1X network in Craig's history, so the form would be unused UI. If one ever +appears, nmtui adds it once and the module activates it thereafter. Spec: +[[file:docs/design/2026-06-29-waybar-network-module-spec.org][2026-06-29-waybar-network-module-spec.org]]. +** CANCELLED [#B] Migrate terminal emulator from foot to ghostty :tooling: +CLOSED: [2026-06-28 Sun 13:58] +:PROPERTIES: +:LAST_REVIEWED: 2026-06-24 +:END: +Decision (Craig, 2026-06-24): switch from foot to ghostty. Drivers: ligatures (foot won't add them) and kitty-graphics + sixel image support (foot is sixel-only, no kitty-graphics plans). ghostty is pure-Wayland on Hyprland, declarative config that fits the theme system, runtime config reload (keybind / SIGUSR2 since 1.2). Trade-off accepted: slightly higher input latency than foot. Already in use as Emacs's terminal renderer, so the config + rendering are familiar and the 06-18 tmux theme was tuned against that surface. Full evaluation: [[file:docs/2026-06-10-terminal-emulator-evaluation.org][docs/2026-06-10-terminal-emulator-evaluation.org]]. + +Migration scope: +- archsetup: add =ghostty= to the package list; decide whether to keep =foot= installed as a fallback or drop it. +- dotfiles: port =foot.ini= → ghostty config (flat key=value). The shared foot.ini sets no font (per-host via =host.ini= include) — replicate that per-host font split for ghostty. +- Themes: the dupre/hudson =themes//= dirs hold foot configs; add ghostty theme files and teach =set-theme= to write + reload the ghostty config. Watch the reload-clobbers-OSC-10/11 bug (ghostty #2795) when wiring runtime theme switch. +- hyprland.conf: default-terminal keybind, pyprland scratchpad terminals, and any other =foot= references → ghostty. +- Verify on velox + ratio: ligatures render, latency acceptable in tmux+vterm use, dupre theme correct, sixel/kitty-graphics previews work. +** DONE [#C] Scratchpad launch turns on focus-follows-mouse :bug:hyprland: +CLOSED: [2026-06-28 Sun] +:PROPERTIES: +:LAST_REVIEWED: 2026-06-28 +:END: +Root cause: =float_switch_override_focus = 1= in hyprland.conf. With =follow_mouse = 0=, focus still jumped to the window under the pointer when it crossed a floating-tiled boundary, so launching a floating scratchpad re-enabled focus-follows-mouse onto tiled windows. Fixed by setting it to 0 (dotfiles =5619342=). Not a pyprland side effect. + +Imported from roam inbox 2026-06-25. Repro: with two tiled windows, moving the mouse over the other tile does nothing (focus-follows-mouse off, as expected). Then launch a terminal (scratchpad), move the mouse over a tile, and focus now switches to the window under the pointer. Something about the scratchpad/terminal launch flips focus-follows-mouse on. Find what re-enables it (likely a Hyprland focus/input setting or a pyprland scratchpad side effect) and keep it off. +** DONE [#B] mod+J/K focus navigation: raise to front, reach floating, monocle fix :feature:bug:hyprland: +CLOSED: [2026-06-29 Mon] +Three improvements to =layout-navigate= (mod+J/K), validated live on velox: +- Raise the focused window to the front on focus navigation, so focusing a window behind an overlapping floating one brings it forward (dotfiles =5619342=, bundled with the =float_switch_override_focus = 0= scratchpad fix tracked above). +- Cycle into floating windows, so you can navigate back to a scratchpad like any window instead of it being a one-way trip (dotfiles =f2107f7=). +- Fixed a monocle regression from that change: the =cyclenext= dispatcher no-ops between monocle-stacked tiles, so focus navigation now computes the workspace window list and focuses the next/prev by address — layout-independent and floating-inclusive (dotfiles =09815f3=). +** CANCELLED [#C] archsetup Waybar Wi-Fi module should show no-internet state :feature:waybar: +CLOSED: [2026-06-29 Mon] +Consolidated, not dropped: the no-internet/captive indicator + the diagnostics/ +bounce/speed-test scope are now Phase 1 + Phase 3 of the unified +[[*Waybar network module — custom/net][Waybar network module — custom/net]] parent. The work continues there; +this separate entry is retired so it's tracked in one place. Spec: +[[file:docs/design/2026-06-29-waybar-network-module-spec.org][2026-06-29-waybar-network-module-spec.org]]. +** CANCELLED [#B] Audit dotfiles/common directory +CLOSED: [2026-06-28 Sun] +Refiled to the standalone =~/.dotfiles= repo, which owns this content since the 2026-06-16 split. Handoff sent 2026-06-28: =~/.dotfiles/inbox/2026-06-28-1335-from-archsetup-refiled-from-archsetup-task-audit-2026.org=. The three sub-tasks (review ~/.local/bin scripts, remove orphaned configs, verify stowed files are used) travel with it. Cancelled here, not abandoned. +** CANCELLED [#C] Zoom launches in a tiny window :bug:hyprland: +CLOSED: [2026-06-28 Sun 13:56] +:PROPERTIES: +:LAST_REVIEWED: 2026-06-24 +:END: +From the roam inbox: Zoom opens at a tiny size. Needs diagnosis (HiDPI scaling vs a window rule vs XWayland) and live verification with Zoom actually running — held for a Craig-driven debug pass, not a blind fix. +** DONE [#B] btrfs base VM unbuildable — archangel ISO bakes zfs-auto-snapshot :bug:test: +CLOSED: [2026-06-28 Sun] +Resolved: archangel shipped a fixed ISO (2026-06-27) that conditions the baked AUR list on the filesystem, so a btrfs install no longer drags in =zfs-auto-snapshot=. The btrfs base rebuilt and went green in the 2026-06-28 VM run (97/0, zero attributed issues). The EFI removable-fallback hardening is archangel-side and optional. +=make test-vm-base= (btrfs) fails in archangel's installer: the ISO bakes a fixed +AUR list ("downgrade yay informant zrepl pacman-cleanup-hook zfs-auto-snapshot +topgrade ventoy-bin") into every install regardless of =FILESYSTEM=. On a btrfs +install =zfs= isn't present, so =zfs-auto-snapshot='s =zfs= dependency can't +resolve and the unattended pacstrap aborts ("unable to satisfy dependency 'zfs' +required by zfs-auto-snapshot"). This is an archangel ISO bug (the baked list isn't +controllable from =archsetup-test.conf=), so it blocks btrfs-profile VM testing +until archangel ships an ISO that conditions the AUR list on the filesystem (or +drops zfs tooling from non-zfs installs). The 2026-06-27 btrfs base regen attempt +also wiped the prior (unbootable) btrfs base, so there's no btrfs base image until +this is fixed. zfs-profile testing works (=make test FS_PROFILE=zfs=). + +Companion hardening (defense-in-depth, archangel-side): install the bootloader +with a removable =\EFI\BOOT\BOOTX64.EFI= fallback so a base boots even from +fresh/empty NVRAM, and real installs survive firmware that drops boot entries. +** DONE [#B] Network panel UI — review findings :feature:waybar:network: +CLOSED: [2026-07-01 Wed] +Full UI review 2026-07-01 (visual walk of every state + code pass over the view logic), 30 findings: 21 from the agent review + color audit, 9 from Craig. All fixed the same night in a no-approvals speedrun, five commits, each test-gated (33 suites) and the whole panel re-verified via AT-SPI smoke + screenshots. + +*** 2026-07-02 Wed @ 00:00 -0400 Theme pass: contrast, hierarchy, focus, hover, destructive, dialogs (dotfiles 82aad0b, 998829b) +Selected-row captions turned cream (the dim gray measured 2.2:1 on the slate fill, a WCAG fail on the auto-selected active row). Names gained weight and captions dropped a size (type hierarchy beyond color). Focus rings gold, scrollbars slim slate, rows got a hover wash. Disconnect and Forget became terracotta destructive-action (red = off). The Join/Add dialogs carry the dupre contract now (ground, mono, styled entries with a gold focus border, no stock blue anywhere), the Add dialog disables its action button until the SSID is non-empty, its password field gained the peek icon, and long SSIDs ellipsize. + +*** 2026-07-02 Wed @ 00:00 -0400 Connections logic: lies, gaps, races (dotfiles 693f820) +Saved profiles stopped claiming "open" (security shows only when the scan knows it; subtitles are view-aware — Available adds signal %, Saved says just "out of range"). An active wired connection pins above the wifi scan in Available. Add connects immediately (Craig's decision), both add dialogs' action reads Connect. Rescan went through the op state machine (the dead guard let double-clicks double-scan). A failed initial load shows in the boxes with a retry instead of stranding "Loading…". Available's first message is "Scanning networks…". Live-info ages humanize (7m, not 445s). A held portal replaces the internet line (stable row height under the poll). The poll pauses on other tabs. VPN profiles got a VPN glyph. Forgetting the active network warns it will disconnect you. + +*** 2026-07-02 Wed @ 00:00 -0400 Diagnostics restructure: selector, live speed test, streamed verdicts, leaner chrome (dotfiles 787b475) +The six-button wall became a dropdown tool selector (full tool names, a description of the selection, one Run button) revealed under Advanced. Speed Test became Network Performance: a reveal with Run Speedtest + Stop (no button-flips-to-Cancel), a once-a-second elapsed ticker while running, and Download / Upload / Ping (high-latency warn) / Server / Tip rows in the diagnose aesthetic. Get Me Online streams the diagnose rows first, announces each attempt ("Trying Reset Connection…"), then its result, and closes with a bold verdict row — as do diagnose, the single tools, and the portal login; verdicts left the status line. Get Me Online at a held captive portal opens the login flow (doctor runs the safe, reversible portal-login when fix is requested). Connecting to a network that turns out captive sends a desktop heads-up, waits a beat, then opens the login page. Diagnose evidence humanized ("open internet (HTTP 204)", "names resolve (captive.apple.com)"). The title row and Close button are gone (Esc + focus-loss auto-hide cover a transient popup) and the status line became a self-clearing toast. The AT-SPI driver anchors on the Diagnostics tab now. +** DONE [#B] Advanced repair buttons: half width, two per row :feature:waybar:network:quick: +CLOSED: [2026-07-01 Wed] +The wide Advanced buttons shrink the panel and leave the diagnostics output impossible to read. Make each half width, two to a row, and rename where needed to fit. Origin: roam inbox capture. + +Done 2026-07-01 (dotfiles aca6827): the Advanced reveal became a 3-column, 2-row grid (Diagnose, Unblock WiFi, Reset / Restart, Test DNS, Force Portal) per Craig's follow-up; labels shortened, tooltips carry the full descriptions. Verified live + AT-SPI smoke. +** DONE [#B] Panel action-button rows fill the panel width :feature:waybar:network:quick: +CLOSED: [2026-07-01 Wed] +Disconnect / Rescan / Add / Add Hidden, and the Saved row, should be as wide as the panel and the buttons above them. Apply the same homogeneous full-width treatment used on the Available / Saved sub-tabs. Origin: roam inbox capture. + +Done 2026-07-01 (dotfiles aca6827): both Connections action rows are homogeneous full-width, which also fixed the panel resizing when Connect flips to Disconnect. Verified live. +** DONE [#B] Live connection info in the row subtitle :feature:waybar:network: +CLOSED: [2026-07-01 Wed] +The live connection information shown in the row hover should also appear in the small print under the connection name, updated in realtime like the hover. Origin: roam inbox capture. + +Done 2026-07-01 (dotfiles aca6827): a 1.5s poll fills the active row's subtitle with the bar-tooltip fields minus the SSID (signal, interface, internet + age, portal note, throughput), sharing the bar's per-field formatters. Verified live. +** DONE [#B] Bake captive-portal login into the net panel :feature:network: +CLOSED: [2026-07-01 Wed] +Make the captive-portal login a first-class net-panel feature instead of the one-off =~/.local/bin/hotel-wifi= script. When the engine sees a held portal, offer "Log in to this network" that runs the plain-DNS + clean-browser flow reversibly (disable DoT -> recover the portal URL from the redirect -> open a clean Chrome profile -> restore DoT when online). Reconcile with the existing =net portal= / =captive= helper, whose DNS-hijack-to-gateway model did NOT match the real Hyatt portal. + +Full mechanism writeup, the working script, and the integration plan: [[file:docs/design/2026-06-30-captive-portal-login.org]]. From the 2026-06-30 Hyatt saga. + +*** 2026-06-30 Tue @ 11:40 -0400 Engine core landed (dotfiles a7d7559) +Replaced =net portal='s old captive-helper hand-off with a =portal-login= repair tier: drop DoT to plain DNS, probe the portal URL (302 / meta-refresh), open a throwaway browser profile, spawn a detached watcher that restores DoT once online (or on timeout). =net portal --restore= is the manual fallback. 7 tests. So =net doctor= / the bar's =net portal= hookups already run the real flow now. Remaining: (1) name the DoT-blocking cause in =net diagnose=; (2) a dedicated "Log in to this network" button in the panel's Diagnose/Repair tab (today it rides the generic =net portal=); (3) live validation against a real captive portal (unit-tested only — didn't run it live to avoid disrupting a meeting). + +*** 2026-07-01 Wed @ 22:41:51 -0400 Live-validated end to end against a local captive simulator (dotfiles c1401db) +The last remainder. tests/net/captive_sim.py is a local redirect portal (302s to a login page until "logged in", then a clean 204). NET_PROBE_URL and NET_PORTAL_TRIGGERS point the whole flow at it (an overridden probe skips the interface binding, which can't reach loopback). Ran live on velox, both restore paths verified: online-detect (login click, watcher saw the 204, DoT drop-in restored within ~2s, clean exit) and the timeout fallback (a watcher that never saw online restored DoT at its 300s deadline). Real sudo mv, real resolved restarts, real redirect URL recovery, real clean-profile Chrome — against a temp drop-in dir, so live DNS was untouched. All three remainders are done; the task is closed. The remaining what-if is a real venue's walled-garden quirks, which only an actual portal exercises. + +*** 2026-07-01 Wed @ 21:44:05 -0400 Diagnose names the DoT block; panel gained Log in to This Network (dotfiles 51e0e2d) +Remainders 1 and 2 landed. The dns-resolve step names the DoT pin when resolution is dead and the drop-in exists (sysio.dot_forced), and routes next_action to the portal login. The panel's hidden Open Portal button became a first-class suggested-action "Log in to This Network", shown whenever the report holds a portal signal (portal step with or without a URL, or the DoT-blocked resolution) via the unit-tested viewmodel.wants_portal_login. TDD, 33 suites green. Remainder 3 (live validation against a real portal) still open. + +*** 2026-06-30 Tue @ 14:59:53 -0400 Live test on velox surfaced two fixed bugs + a deeper follow-up +Force portal (panel Repair tab) = =net-popup net portal= = the same portal-login tier. Tested live on @Hyatt_WiFi (already authorized, so no real intercept). Two bugs fixed in dotfiles (TDD, full suite green): +- Chrome first-run wizard fired on every launch — =_open_portal= made a fresh tempfile profile but passed no first-run flags. Added =--no-first-run --no-default-browser-check= + a unit test. +- Flashing sudo prompt for the DoT drop + pointless resolved restart on velox, where the DoT drop-in the code looks for (=/etc/systemd/resolved.conf.d/dns-over-tls.conf=) doesn't exist. Guarded =_disable_dot=/=_restore_dot= to be true no-ops (no sudo, no restart) when there's no DoT drop-in to move; tests assert no systemctl call fires. +** DONE [#B] Consistent red=off across waybar toggle modules :waybar: +CLOSED: [2026-07-01 Wed] +Extend the red=off convention (just added to the touchpad/mouse indicator) to the other toggles — sound volume, microphone mute, and caffeine — so a disabled / muted / off state reads red across the board. Skip the "cross"/slash; the color alone carries it. Origin: roam inbox capture. + +Already implemented (verified 2026-07-01): =style.css= gives =#pulseaudio.muted=, =#pulseaudio.mic.source-muted=, and =#custom-caffeine.inhibited= the off-state color =#d47c59=, matching =#custom-touchpad.disabled=. Note: caffeine's red fires on =.inhibited= (caffeine ON / staying awake), which is arguably the inverse of "off" — leave as-is unless you want strict off=red semantics there. +** DONE [#B] Microphone-mute keybind :feature:waybar:quick: +CLOSED: [2026-07-01 Wed] +A keyboard shortcut to toggle the mic mute. The pulseaudio#mic module shows the state but there's no hotkey to flip it. Wire a hyprland bind to a mic-mute toggle. Origin: roam inbox capture. + +Already implemented (verified 2026-07-01): hyprland.conf binds both =XF86AudioMicMute= and =Super+Shift+A= to =mic-toggle= (no conflict — airplane is Super+Shift+X). +** DONE [#C] Alarm tooltip shows time remaining, not alarm time :bug:waybar:quick: +CLOSED: [2026-07-01 Wed] +The =wtimer= alarm tooltip displays the countdown (time remaining) instead of the alarm's wall-clock fire time. For an alarm set to 2:00pm, the tooltip should name the target time, not "1h 23m left". Fix the tooltip rendering in =wtimer= (dotfiles repo). Origin: roam inbox capture. + +Fixed 2026-07-01 (dotfiles): =_describe= now renders an alarm's wall-clock target via a new =format_clock= helper instead of =format_time(remaining)=. TDD test added; full wtimer suite (87) green. +** DONE [#C] Waybar right-cluster module order :waybar:quick: +CLOSED: [2026-07-01 Wed] +Move the timer module to the rightmost position, just left of the systray, and move the battery/sysmonitor module to second-to-rightmost. Config edit in the waybar config (dotfiles hyprland tier). Origin: roam inbox capture. + +Done 2026-07-01 (dotfiles waybar config): =custom/timer= now sits just left of =tray= with =custom/sysmon= second-to-rightmost. waybar regenerated + reloaded live on velox; visual confirmation pending Craig. -- cgit v1.2.3