diff options
Diffstat (limited to 'todo.org')
| -rw-r--r-- | todo.org | 652 |
1 files changed, 380 insertions, 272 deletions
@@ -147,17 +147,143 @@ default, and a udev rule granting the video/input group write access so it works without sudo (a bare ssh session got EPERM). Check whether Fn+Space (EC-handled on Frameworks) already cycles it — if so the bind is a complement, not the only path. Ratio: n/a (desktop). +** TODO [#A] Post-rebuild verification pass :feature:velox: +DEADLINE: <2026-08-16 Sun> +:PROPERTIES: +:CREATED: [2026-08-14 Fri] +:LAST_REVIEWED: 2026-08-14 +:END: +A rebuilt machine looks finished and isn't. Five gaps surfaced on velox +within two days of the 2026-08-13 reinstall, and three of them LOOKED +fine: a stowed unit file, an enabled timer, a present git clone. From the +.emacs.d handoffs 2026-08-14 (inbox, both PROCESSED) plus what this +session found independently. +The generalizable fix is one pass the installer runs at the end, or a +=post-rebuild-check= script the checklist points at. Each item is cheap +and turns a silent no-op into a visible line: +1. =systemctl --user list-units --state=failed= — calendar-sync had been + failing every 15 minutes for two days with nobody watching. +2. Every stowed/linked user unit that is NOT enabled. roam-sync and + signal-receive came back linked and inert; two others were never + linked at all. A unit file being present is not the same as running. +3. Every tracked =*.local.el.example= (or =*.local.*=) with no sibling + real file. Three exist in .emacs.d; all three were gone on velox. +4. Every gitignore-mode project missing its =.ai/=, =.claude/=, + =CLAUDE.md=, =todo.org=, =inbox/=. A reinstall drops the entire + working state of every such project — 374 files and 4.5 MB in + .emacs.d's case — and nothing carries it: not git, not stow, not the + bootstrap. +5. =signal-cli listAccounts= non-empty. velox lost its registration, and + because agent-text relays to a hardcoded velox, that breaks the phone + channel for the WHOLE FLEET, not just this machine. +Graded [#A] because item 5 is live right now and silently disables +paging, and because the flight is Sunday. +** TODO [#B] Restoring a git repo from backup can resurrect a dangerous diff :bug: +:PROPERTIES: +:CREATED: [2026-08-14 Fri] +:LAST_REVIEWED: 2026-08-14 +:END: +My 2026-08-14 restore of =~/org= from the salvage brought back roam's +=.git= deliberately ("simpler, preserves everything exactly"). It also +brought back a clone ten commits stale AND an uncommitted =inbox.org= +emptied to zero bytes. roam-sync is the repo's only committer and commits +whatever it finds, so enabling that timer would have committed the +emptying and pushed it — deleting the live inbox items ON RATIO. A +.emacs.d session caught it, verified ratio's copy was a strict superset, +discarded the local diff, fast-forwarded, and only then enabled the timer. +Lesson to encode somewhere durable: restoring a git repo from a backup is +not the safe option it looks like. For any repo with a live remote, +re-clone and carry only proven-needed work; where a backup copy is +restored anyway, reconcile it against the remote BEFORE any +auto-committing timer is enabled. The failure here would have been silent +and landed on a different machine. +** TODO [#B] Nothing installs the .emacs.d systemd user units :bug:velox: +:PROPERTIES: +:CREATED: [2026-08-14 Fri] +:LAST_REVIEWED: 2026-08-14 +:END: +=~/.emacs.d/systemd/= ships four user units (agenda-render-cache +service+timer, calendar-sync service+timer). On ratio they are symlinked +into =~/.config/systemd/user/= by hand. Nothing does that on a fresh +machine: they are not stowed (they live in .emacs.d, not dotfiles) and +archsetup does not link them. +Consequence found on velox 2026-08-14: the world wallpaper face drew +nothing, because it reads =~/.cache/settings/agenda.json= and the timer +that exports it was never installed. Calendar sync was silently dead for +the same reason — which is the second time that particular timer has gone +missing (see the 2026-08-01 session, where its auto-start was the bug). +Linked and enabled by hand on velox; export verified (316 bytes, 1 event). +Fix belongs in whichever owns the seam: either .emacs.d gains an install +step for its own units, or archsetup links them alongside the dotfiles +stow. Prefer the former — the repo that ships a unit should install it. +Grading: Major severity (two background services silently absent, and the +failure looks like a data problem rather than a missing timer) x every +fresh install = P2 = [#B]. +** TODO [#C] Panel can leave a channel selected with nothing to show :bug:dotfiles: +:PROPERTIES: +:CREATED: [2026-08-14 Fri] +:LAST_REVIEWED: 2026-08-14 +:END: +velox's store carries channel "pair" with pair_sel unset, so +channels.selected_pair() returns None and wallpaper.apply() fails every +time. Found 2026-08-14 when the new session-start restore reported +"unavailable" and fell through to the waypaper fallback — the machine +still showed dark-lion, which looks exactly like the bug that was just +fixed. ratio is fine (channel world, pair_sel 0). +Two candidate fixes, needs a call: either the panel refuses to switch to a +channel whose selection is empty, or apply() falls back to the first +minted pair/set when the index is unset. The second is friendlier and +matches "the store is the source of truth" — a channel with exactly one +plausible reading should not be a dead end. +Grading: Minor severity (one fallback still puts a wallpaper up) x some +users sometimes = P3 = [#C]. +** TODO [#B] Land the rescued emacs-wttrin commit :chore:velox: +:PROPERTIES: +:CREATED: [2026-08-14 Fri] +:LAST_REVIEWED: 2026-08-14 +:END: +bf0457f "feat: add wttrin-hide-follow-line to hide the wttr.in follow line" +(2026-06-24) was the only genuinely unpushed commit anywhere on the old +velox — 3 files, 103 insertions, with a test file. Rescued as a verified +git bundle before the disk was wiped: +[[file:working/velox-reinstall/wttrin-bf0457f.bundle][working/velox-reinstall/wttrin-bf0457f.bundle]] +To land it: clone emacs-wttrin, =git fetch <bundle> --branches=, review the +commit, then push to git@cjennings.net:emacs-wttrin.git. Delete the bundle +once it's on the remote. +** TODO [#B] archsetup doesn't clone rulesets :bug:velox: +DEADLINE: <2026-08-15 Sat> +:PROPERTIES: +:CREATED: [2026-08-14 Fri] +:LAST_REVIEWED: 2026-08-14 +:END: +A fresh install has claude but no =ai=, no skills, no rules, no hooks, +because =~/code/rulesets= is never cloned. Found on velox 2026-08-14 when +=ai= wasn't on PATH. archsetup clones dotemacs, dotfiles, the suckless +tools and itself, so rulesets is the one workstation repo it misses, and +without it the whole agent tooling layer is absent on a rebuilt machine. +Fix: clone it alongside the others (=RULESETS_REPO=, defaulting to +git@cjennings.net:rulesets.git) and run =make install= afterwards, which +is what links the 54 symlinks into ~/.claude and ~/.local/bin. Graded +Major severity (a rebuilt machine silently loses every agent workflow) +x most-users-frequently = P2 = [#B]. Worked around by hand on velox +already; this is the durable half. ** TODO [#B] Hibernate in the settings dial power actions :feature:dotfiles: :PROPERTIES: :CREATED: [2026-08-13 Thu] :LAST_REVIEWED: 2026-08-13 :END: Add hibernate alongside suspend/lock in the settings module's dial power -actions. Sequencing (Craig confirmed the dial placement 2026-08-13): -1. Prove hibernate on velox first — systemctl hibernate through a real - resume; the chain (LUKS swap p3, keyfile-in-initramfs, encrypt+resume - hooks, resume= on the ZBM cmdline) went live with the 2026-08-13 - reinstall but is untested on this AMD board. +actions. The wlogout exit menu already carries it (keybind h) and needs no +work; the dial is the remaining surface. Sequencing (Craig confirmed the +dial placement 2026-08-13): +1. DONE 2026-08-14 00:14 — hibernate proven end to end on velox, driven + from the exit menu so the wiring was exercised too. Evidence: the boot + id was unchanged across the cycle (f14152f9…) and uptime kept counting + 3h15m → 3h18m, so it genuinely resumed rather than rebooting; the + journal carries "PM: hibernation: hibernation exit" and the + HibernateLocation EFI variable being cleared. Took 9.3s wall. The whole + chain works: suspend-to-disk into the LUKS-encrypted swap, resume via + the keyfile embedded in the initramfs, one passphrase at ZBM. 2. Then consider suspend-then-hibernate as the default lid behavior (systemd sleep.conf HibernateDelaySec) — hibernate's savings with no button at all; possibly a "deep sleep" toggle in the module. @@ -223,78 +349,6 @@ items needing your call say so. if you disagree). Found tonight, low priority: the orchestrator sequence pin can't see an added-but-unstubbed call (it caught drops only) — worth a harness hardening pass someday. -** DONE [#B] Podman API socket and camera-passthrough udev rule :feature:solo: -CLOSED: [2026-08-09 Sun] -:PROPERTIES: -:CREATED: [2026-08-07 Fri] -:LAST_REVIEWED: 2026-08-07 -:END: -Shipped 2026-08-09: the installer enables the rootless podman socket at -install time (enable_user_service grew a wants-target arg so socket units -land in sockets.target.wants) and ships -=72-usb-passthrough-cameras.rules= — numbered below 73 per the winvm -rule-ordering correction, GROUP/MODE as the verified grant, uaccess tag kept. -Applied live on ratio (socket enabled+active, 99- file retired, udev -reloaded); velox apply rides the velox-return riders on the sleep/suspend -task. The uaccess-alone hypothesis stays untested until a camera is attached. -From winvm 2026-08-07 (ratio). Two one-time machine-level setups, both live on -ratio and absent on velox; full evidence and rationale in -[[file:docs/design/2026-08-07-podman-socket-and-camera-udev.md]]. - -- Enable the rootless podman socket at install time - (=systemctl --user enable --now podman.socket=). Socket-activated, zero idle - cost; every podman GUI/API client needs it, and its absence fails silently - (Pods opens to an empty window). The installer already carries the - "=systemctl --user enable= fails during install" workaround pattern - (=archsetup:1270=, =:2722=) — use it. -- Ship a udev rule granting GROUP="video", MODE="0660" on the OBSBOT - (3564:ff02) and BRIO (046d:085e) USB nodes so =usbredirect= can claim them - for VM passthrough. CORRECTED (winvm, 2026-08-08): the original "uaccess - can't ACL raw USB nodes" claim was wrong — the mechanism is rule ordering. - The ACL is applied by =73-seat-late.rules=, so a =99-= rule adds the tag - after that already ran; distro rules that add the tag all sort at or below - 70. So number our file below 73 (e.g. =72-usb-passthrough-cameras.rules=), - keep the verified GROUP/MODE grant, and keep the tag — correctly ordered it - may make uaccess work on its own (untested hypothesis; a tighter grant if - it holds, needs the camera plugged in to verify). Reconcile ratio's - existing =99-= file (winvm installed it) when the installer version lands. - -Scope: installer step + rule file + tests per existing shapes, and apply both -live to velox over tailscale (daily-driver sync — neither exists there today). -:PROPERTIES: -:CREATED: [2026-07-28 Tue] -:LAST_REVIEWED: 2026-07-28 -:END: -Craig, from the roam inbox 2026-07-28: "launching into wayland doesn't honor previous caffeine settings ...or I expect any other settings in the desktop settings module." Captured right after the 08:59 reboot. - -Confirmed, and it generalizes past caffeine. The settings module splits cleanly into two halves, and only one of them persists. - -Persisted, in =~/.config/desktop-settings/state.json= (=store.py= =DEFAULTS=): program slots, idle-tripper stages, wallpaper. These come back correctly. - -Not persisted — every one is derived live from a process or a compositor runtime option, so a session restart resets it to whatever =hyprland.conf= establishes: -- Caffeine — =caffeine_state()= is =pgrep -x hypridle= inverted, and =hyprland.conf:73= runs =exec-once = pkill -x hypridle; hypridle=. So every launch unconditionally starts hypridle, which means caffeine is *always* OFF after login. There is no code path that could restore it ON. -- Auto-dim — =dim_state()= reads =hyprctl getoption decoration:dim_inactive=, a compositor runtime value that resets to the config default on restart. -- Night light — =state()= is =pgrep -x gammastep=; the process dies with the session. -- DND — =dunstctl=; dunst restarts fresh from =exec-once=. -- Power profile / brightness — owned by powerprofilesctl and systemd-backlight, outside this module's scope. - -Verified live 10 minutes after the reboot: hypridle running (caffeine OFF), dim =false=, gammastep not running, dnd =false=, power =balanced=. Every toggle sat at its factory position. - -The failure is silent, which is what makes it bite: nothing tells you the value you set was discarded. That is the mechanism behind the 2026-07-27 lockout, where Craig believed caffeine was on and the screen locked anyway. - -Grading: Major severity (the panel's core promise is holding these values, and the reset is silent and total across all four toggles) x most users frequently (every session start resets them, though it only harms when a deliberate non-default was set) = P2 = [#B]. - -Not :solo: — the fix needs Craig's call on *which* toggles should persist and whether persistence is per-toggle opt-in. Restoring night light at 3pm or caffeine on a laptop are both plausibly wrong, so this is a preference question, not a derivable one. The mechanism itself (extend =store.py= with a =toggles= block, restore on session start) is mechanical once that's settled. - -Related: =[#B] Caffeine state is unreadable on both surfaces= covers display accuracy — whether the surfaces report the truth. This covers whether the value survives at all. Distinct bugs, same subsystem. - -*** Side finding — gammastep loses a startup race and nothing relaunches it -=hyprland.conf:75= runs =exec-once = gammastep=, but no gammastep process is alive. Today's three launch logs tell the story: =gammastep-2026-07-28-090034.log= carries "Wayland connection experienced a fatal error: -1 / Temperature adjustment failed", and the other two are empty. - -Launched by hand afterward it runs fine and survives, so gammastep is not broken — it loses a race against compositor readiness at session start. Nothing relaunches it, so night light is simply off for the whole session, silently. (An earlier read of this said night light "has likely never worked from the config". That was wrong: the failure is a startup race, not a permanent break.) - -Worth its own task — the fix is a readiness wait or a retry around that exec-once, not a persistence change. Filed here for now because it surfaced during this investigation. - ** TODO [#C] Re-apply the active program at session start :refactor:dotfiles:hyprland: :PROPERTIES: :CREATED: [2026-07-30 Thu] @@ -421,33 +475,6 @@ Not :solo: — the rearrangement is described but not settled, and the result is Related: =[#C] Add a time selector to the timer panel= covers a duration picker for the same input area. Design them together when either is picked up. -** DONE [#A] Comet KVM setup for truenas :feature:infra:truenas: -CLOSED: [2026-08-08 Sat] -:PROPERTIES: -:CREATED: [2026-07-27 Mon] -:LAST_REVIEWED: 2026-07-27 -:END: -Resolved: Craig wired up and configured the Comet himself, confirmed working -2026-08-08. The ATX power-board follow-up (hard power-cycle for a truly wedged -box) remains unfiled — raise it if the next outage shows the KVM alone isn't -enough. -Wire up the GL.iNet Comet (GL-RM1) IP KVM against truenas. It was bought 2026-01-14 for exactly this job and its KB node still reads "Arrived, not yet set up." - -Why now: truenas went dark 2026-07-24 and stayed unreachable. Diagnosis from ratio on 2026-07-27 — no tailnet contact for 3 days, 100% packet loss on 192.168.86.5, ARP entry FAILED (nothing answers ARP for the address, so the NIC is down at layer 2), every service port closed, while the gateway and a dozen other LAN hosts stayed reachable. Wake-on-LAN to 70:85:c2:db:9d:94 drew no response. With no console and no out-of-band power control there was no remote remedy at all, so recovery needed hands on the box. The Comet closes exactly that gap: BIOS/UEFI console, Wake-on-LAN, and browser access over its native Tailscale integration. - -Not :solo: — the physical cabling is Craig's, and the Tailscale enrollment needs his account. - -Steps, from the KB node ([[id:67bc5994-a763-48e2-926f-4ac0d1bad3db][GL.iNet Comet (GL-RM1) - KVM]]): -1. HDMI from truenas video out to the Comet's HD IN. -2. USB-A-to-USB-C from the Comet to a truenas USB port (keyboard/mouse emulation). -3. Ethernet to the network. -4. Power via USB-C (5V/2A). -5. Reach the web interface and enroll it in Tailscale, so it's usable when the LAN side of truenas is the thing that's broken. - -Then verify while truenas is healthy, rather than discovering the gaps during the next outage: confirm the console shows POST and the BIOS, that keyboard input reaches the box, and that Wake-on-LAN from the Comet actually powers it on. Enable WOL in the truenas BIOS if that last check fails — this outage never established whether it was on. - -Worth considering as a follow-up: the ATX power board accessory gives hard power-cycle control for a truly wedged box, which the KVM alone can't do. - ** TODO [#C] Post-upgrade hooks: compositor restart reminder + font cache rebuild :feature:infra:ratio:solo: :PROPERTIES: :CREATED: [2026-07-25 Sat] @@ -585,7 +612,7 @@ doc above (not published, since they map the setup). Follow-ons: the rotation VERIFY above, velox reconcile on return, the secrets-repo split (top of Open Work), the wireguard =.gitignore= bug (line ~191), the cgit move (below), and a pre-receive secret-scan hook so this can't recur. -*** TODO [#B] velox: reconcile its clones after the history rewrite +*** TODO [#A] velox: reconcile its clones after the history rewrite velox was offline for repair during the 2026-08-09 purge, so its clones still hold the pre-rewrite history and are diverged from the rewritten remotes. On its return: force-fetch + rebase local work onto the rewritten main in both @@ -1099,79 +1126,6 @@ Boot the configured endpoint and send a short prompt; surface success/failure + Acceptance: fresh VM install of the ratio profile reaches an endpoint on =:8081= that answers a smoke prompt; velox profile gets Q4_K_M + 8B and answers a prompt within reasonable laptop latency; network-down install completes successfully with the pending-models warning surfaced. -** DONE [#A] Review post-archsetup laptop setup steps (velox 2026-04-10) -CLOSED: [2026-08-08 Sat] -:PROPERTIES: -:LAST_REVIEWED: 2026-08-08 -:END: -Closed at the 2026-08-08 session: every open item got its automate-vs-document -call and the work landed the same night (tests green, committed). Residual: -velox itself still needs the new tlp.d radio line and a dotfiles pull — folded -into the [#A] sleep/suspend task, which works the same files on velox anyway. -Items discovered during velox setup that needed manual intervention after archsetup. -Decide which should be automated in archsetup vs documented as post-install steps. - -*** 2026-08-08 Sat @ 04:43:42 -0500 Automated radio enable via TLP (rfkill boot soft-block) -Root cause sharpened during triage: archsetup masks systemd-rfkill on laptops -(it fights TLP), so nothing restored radio state at boot — the "unblock once -should stick" premise was wrong under the mask. Fix in the TLP custom conf: -=DEVICES_TO_ENABLE_ON_STARTUP="bluetooth wifi"=, the TLP-native mechanism. -configure_tlp_power parametrized for tests; covered by -tests/installer-steps/test_configure_tlp_power.py. - -*** 2026-07-04 Sat @ 11:48:24 -0500 Automated /efi restrictive mount permissions in fstab generation -archsetup:2827-2836 now rewrites the /efi fstab line to =fmask=0177,dmask=0077= (idempotent), so fresh installs no longer land the world-accessible =fmask=0022,dmask=0022= default. Confirmed via the 2026-07-04 task audit. (Original velox note: default vfat mount had =fmask=0022,dmask=0022=, hand-fixed to restrictive; bootctl warned about a world-accessible random-seed file.) - -*** 2026-08-08 Sat @ 04:43:42 -0500 Automated tmp.mount mask for ZFS /tmp -New mask_tmp_mount_for_zfs, called from configure_snapshots' ZFS branch: -masks tmp.mount only when the pool actually carries a dataset mounted at -/tmp (exact match), silent no-op without zfs or without the dataset. Covered -by tests/installer-steps/test_mask_tmp_mount_for_zfs.py; the orchestrator -dispatch pin updated. - -*** 2026-08-08 Sat @ 04:43:42 -0500 Automated CPU microcode install by vendor -New install_cpu_microcode, first in boot_ux so grub-mkconfig and mkinitcpio's -microcode hook both see the installed /boot/<vendor>-ucode.img: vendor_id from -/proc/cpuinfo → intel-ucode / amd-ucode, error_warn on unknown vendor. -Covered by tests/installer-steps/test_install_cpu_microcode.py; boot_ux -sequence pin updated. - -*** 2026-07-04 Sat @ 11:48:24 -0500 Automated syncthing user-service enable in archsetup -archsetup:2263-2271 now installs syncthing and enables the user service (via symlink), so fresh installs no longer leave it installed-but-disabled. Confirmed via the 2026-07-04 task audit. (Original velox note: package installed but service not enabled; hand-fixed with =systemctl enable --now syncthing@cjennings=.) - -*** 2026-08-08 Sat @ 04:43:42 -0500 Closed the awww-daemon crash watch — no recurrence -The April boot crash never recurred across four months of daily use on both -machines (and the wallpaper stack has since been reworked). Reopen as its own -bug with fresh evidence if it ever comes back. - -*** 2026-08-08 Sat @ 04:43:42 -0500 Automated touchpad device detection in the pointer scripts -The scripts were already in stowed dotfiles with binds — the open half was the -hardcoded Framework device name. Both touchpad-auto and toggle-touchpad now -auto-detect the touchpad (first pointer named *touchpad*, pixa fallback) and -derive the internal-pointer exclusion set from the detected name, so they -agree on any machine. Test seams added (--detect / --has-external-mouse); -tests/touchpad-auto/ new, toggle-touchpad suite still green. Dotfiles commit; -velox picks it up on its next pull. - -*** 2026-08-08 Sat @ 04:43:42 -0500 Documented bluetooth pairing in the post-install checklist -Inherently interactive, so it can't ride the installer. Documented in the new -[[file:docs/post-install-checklist.org][docs/post-install-checklist.org]] along -with the Proton Bridge steps — the standing home for manual post-install work. -Consider: document as post-install step. No automation possible. - -*** 2026-05-26 Tue @ 13:32:31 -0500 pocketbook install concern moot — pulled from publication, folded in-tree -Resolved by removing pocketbook from archsetup's provisioning entirely. It's nowhere near ready, so the github mirror + cjennings.net repo were deleted and the project was folded into the archsetup tree at =pocketbook/=. Dropped the =gtk4-layer-shell= dep + =pip_install= from =archsetup= and the clone from =scripts/post-install.sh=. No fresh install pulls pocketbook now, so "not installed on velox" no longer applies. Re-wiring the install is tracked in the new pocketbook development backlog. - -*** TODO Review: Tailscale needs login after install -~tailscaled~ service was enabled but needed ~tailscale up~ for interactive auth. -Old machine entry needed cleanup in admin console. -Consider: document as post-install step. - -*** TODO Review: docs/ directories need manual sync from existing machine -docs/ dirs (gitignored) for ~/code and ~/projects repos needed scp/rsync from ratio. -Same for ~/.emacs.d/docs/. Not in git, so not available after clone. -Consider: document as post-install step or create a sync script. - ** TODO [#B] Test + CI infrastructure :test: :PROPERTIES: :LAST_REVIEWED: 2026-07-13 @@ -2123,13 +2077,6 @@ Specced 2026-07-10 after discussion with Craig, and the design grew past the ori Parent spec: [[file:docs/specs/2026-07-09-audio-doctor-spec.org][docs/specs/2026-07-09-audio-doctor-spec.org]] (IMPLEMENTED). This is a v1 gap found after the fact, not a phase of it. -** DONE [#C] Waybar modules run together — need subtle separators :bug:dotfiles:waybar: -CLOSED: [2026-08-08 Sat] -Closed at the 2026-08-08 task review: Craig confirms the separator work landed -a while back and the bar reads correctly now. -Craig misreads where one module ends and the next begins — the wind (weather) value runs straight into the date with no visual stop, so he reads the wind figure as the start of the date. Add a light, subtle separator or spacing between adjacent Waybar modules. -Grading: Minor severity (legibility, nothing broken) x frequent (every glance at the bar) = P3 = [#C]. -Not fully :solo: — needs Craig's eye on the result (separator style is a taste call, plus a live visual check). Prior work added a date-facing divider (dotfiles 103cccb); evidently not enough, so revisit the whole inter-module treatment rather than just the weather/date seam. From .emacs.d handoff 2026-07-20-1114 (roam capture; waybar is archsetup-owned per the dotfiles standing rule). ** TODO [#C] Weather chip color signals unclear + unenforced :bug:dotfiles:waybar:weather: :PROPERTIES: :LAST_REVIEWED: 2026-07-21 @@ -2179,13 +2126,6 @@ already consumes, so the indicator pays nothing new. Where NM can't guess panel affordance for it can come later. Live phone-hotspot check is Craig's manual-testing entry; everything else verifies with fakes. -** CANCELLED [#C] Add a whole-display dim mode :feature:hyprland: -CLOSED: [2026-08-08 Sat] -Killed at the 2026-08-08 task review: the July auto-dim work covers the actual -need; no separate dim-everything mode wanted. -Extend auto-dim with an explicit “dim everything” setting for bright -non-dark-mode contexts, with a security/usability review of its scope. - ** TODO [#C] Net panel speedtest history :feature:dotfiles:network: :PROPERTIES: :LAST_REVIEWED: 2026-07-14 @@ -2222,41 +2162,6 @@ Tool choice is the open decision (needs Craig): =nerd-dictation= (Vosk, lighter, *** 2026-07-21 Tue @ 08:40:00 -0500 Decided (Craig): whisper.cpp + wtype, system-wide STT engine = =whisper.cpp= (accurate offline, optional GPU on ratio's Radeon). Typing backend = =wtype= (Wayland-native virtual-keyboard injection into the focused window, no root/daemon), with =ydotool= (uinput) held as a fallback only if a specific app — some XWayland/Electron surface — won't accept wtype's synthetic input. One system-wide path that also covers Emacs buffers and the Claude Code prompt; the Emacs-native =whisper.el= route was NOT chosen. Build scope: whisper.cpp + a model (start with a mid-size English model, tune later), a Hyprland push-to-talk keybind driving a record→transcribe→wtype pipeline, and an autostart/service entry, folded into archsetup so it lands on ratio + velox. Now unblocked (agent-buildable; verification includes a live dictation check). -** DONE [#C] Fix install errors surfaced by the 2026-05-11 VM test run -CLOSED: [2026-08-08 Sat] -:PROPERTIES: -:LAST_REVIEWED: 2026-07-06 -:END: -Closed at the 2026-08-08 task review: every archsetup-attributable error was -fixed and verified (fontconfig, dconf x2, emacs-stow, AUR exit-0 logging at -the root); the residual four reproduce unchanged and are diagnosed -environment/non-critical, with two 2026-06-28 full runs attributing zero -issues to archsetup. Residual thread: confirm the firewall nf_tables pair on -bare metal at the next real install — no container task needed to carry it. -*** 2026-06-28 Sun @ 13:29:29 -0400 Audit reconcile: 2026-06-28 btrfs+zfs runs reproduce the same residual set -Newer full runs landed since the 2026-06-11 reconcile below: the 2026-06-25 zfs run (Testinfra 96/0) and the 2026-06-28 btrfs+zfs runs (97/0, "zero attributed issues"). The residual four were NOT fixed and reproduce unchanged: =enabling firewall= (archsetup:1496-1498, carries a VM-kernel note), =enabling gamemode for user= (archsetup:2221, non-critical), and =tidaler (AUR)=. Zero archsetup-attributed Testinfra issues across both profiles confirms these are environment / non-critical, not archsetup bugs. Bare-metal confirmation of the firewall pair is still the open thread. - -*** 2026-06-15 Mon @ 23:53:21 -0500 Audit reconcile: latest VM run (2026-06-11) confirms the surviving error set -The most recent VM run (=test-results/20260611-113904/=) carries four error-summary entries: =enabling firewall= + =verifying firewall is active= (the iptables/nf_tables "Could not fetch rule set generation id" pair, still unconfirmed on bare metal), =enabling gamemode for user= (non-critical), and =tidaler (AUR)=. The earlier fontconfig/dconf fixes held — none reappear. So the count is down from the 7→6 anchor below to four, all of them the known-residual items already itemized. -Errors logged during the VM install. Status as of the 2026-05-11 18:36 run (=test-results/20260511-183643/archsetup-output.log=) after the =48c9439= fontconfig/dconf fix: 7 → 6. -- refreshing font cache — RESOLVED in =48c9439= (now installs =fontconfig= before calling =fc-cache=). -- configuring GTK file chooser — RESOLVED in =ecab29f= (switched to a system-wide dconf db at =/etc/dconf/db/site.d/=; needs no session bus during install). -- configuring GNOME interface settings in dconf — RESOLVED in =ecab29f= (same fix as the GTK file chooser above). -- enabling firewall — exit 1: =iptables v1.8.13 (nf_tables): Could not fetch rule set generation id: Invalid argument=. Still present in the 18:36 run; likely a VM-kernel/nf_tables artifact — confirm on bare metal before treating as an archsetup bug. -- verifying firewall is active — exit 1 (follow-on from the firewall-enable error). -- enabling gamemode for user — exit 1 → step "gaming" FAILED — non-critical. -- tidaler (AUR) — logged in the error summary with exit code 0 (odd; logging quirk or transient AUR build noise?). -Also seen in the 18:36 run's log-diff (post-install systemd noise, probably VM-environment): =pam_systemd … CreateSession failed= / =logind: Failed to start session scope … Permission denied=, and =Failed to start Proton VPN Daemon= (no VPN config in the test VM). - -*** 2026-05-19 Tue @ 13:18:56 -0500 Fixed AUR exit-0 logging bug at the root -Root cause was in =retry_install=: =last_exit_code=$?= ran AFTER =if eval ...; then return 0; fi=. Bash defines an if-compound's exit status as zero when no condition tested true, so a failing eval's exit code got overwritten with 0 before reaching =error_warn=. Fix in =8221c54=: capture =$?= from =eval= directly into a local var, then compare against the captured value in the if. VM-verified in =test-results/20260519-115318/=: =mkinitcpio-firmware (AUR)= and =tidaler (AUR)= now report =error code: 1= (yay's actual exit) instead of the misleading =error code: 0=. The same packages still appear in the summary because yay returns non-zero when sub-deps fail to build (e.g. =aic94xx-firmware=), but the codes are accurate now. If the underlying sub-dep failures stay noisy, that's a separate concern — open a new task. - -*** 2026-05-16 Sat @ 09:00:41 -0500 AI Response: Surfaced the expanded AUR-exit-0 pattern -2026-05-16 07:40 VM run passed (52/0/5) with the same warning profile as the 2026-05-11 18:36 run. Error count went 7 → 13: 5 fixed/unchanged, +5 new AUR-exit-0 entries (broadens the existing tidaler item into the dedicated =[#B]= subtask above), +1 genuinely new error in =setting up emacs configuration files= (=git pull= ran in =~/.emacs.d= which existed from stow but had no =.git=). Patched =archsetup:1932-1945= with a three-branch check: clone if missing/empty, pull if =.git= exists, =git init=/=fetch=/=checkout= in place if the dir came from stow. - -*** 2026-05-19 Tue @ 01:25:26 -0500 Verified the b9907c7 emacs-stow fix end-to-end -=make test= 21:44 → 22:29 (42 min), =test-results/20260518-214516/=. 52/0/5, =ArchSetup Exit Code: 0=. The third-branch path fired correctly — install log =archsetup-2026-05-18-21-45-46.log:14358-14365= shows =From https://git.cjennings.net/dotemacs= → =[new branch] main -> origin/main= → =Reset branch 'main'= → =branch 'main' set up to track 'origin/main'=. No exit-128, no =fatal: not a git repository=. Error Summary down to 7 (was 13 on 2026-05-16); the emacs entry is gone. AUR exit-0 logging triggered for 2 packages this run (mkinitcpio-firmware, tidaler) vs 6 on 2026-05-16 — same bug class, fewer triggers, still tracked under =[#B] AUR exit-0 logged as error=. Issue Attribution: 1 ARCHSETUP entry (Proton VPN Daemon failed — known VM-no-VPN-config artifact). Cleanup ran clean via the normal path. - ** TODO [#B] Osbot camera configuration :chore:quick: SCHEDULED: <2026-08-08 Sat> :PROPERTIES: @@ -2305,15 +2210,6 @@ The goal is a single place to edit each config, not two. *** 2026-07-21 Tue @ 08:00:00 -0500 Audit reconcile: single-theme now, so the switch-revert pressure is lower The theme system went single-theme — Hudson was retired (dotfiles e03436e; documented archsetup 98142bb, 2026-07-18), leaving Dupre as the only theme. So "edits get overwritten on theme switch" now bites only rarely (switches are effectively nonexistent). The structural two-places-to-edit problem still stands and is worth fixing, but the urgency the original grading implied has dropped. -** CANCELLED [#C] Review current tool pain points annually -CLOSED: [2026-08-08 Sat] -:PROPERTIES: -:LAST_REVIEWED: 2026-07-06 -:END: -Killed at the 2026-08-08 task review: an undated annual intention that never -fired — pain points get surfaced organically as they bite. -Once-yearly systematic inventory of known deficiencies and friction points in current toolset - ** TODO [#D] Installer + scripts refactor opportunities :refactor:solo: Grading: no behavior change; parking lot. 10 refactors remain from the sentry audit — duplicated GPU-modalias scan, triple hand-rolled retry loop, stow x4, display_server/window_manager dispatch dup, Maia ELO range x3, per-script log helpers, GRUB/snapper/fsck sed clusters, waybar-battery positional sed. Full list with line numbers in [[file:docs/design/2026-07-19-sentry-code-findings.org][sentry code findings]] (High/Medium/Low tagged). Pull individual ones out as their own tasks when tackled. The system-mutation sed clusters (snapper/fsck/GRUB/waybar) want characterization coverage before any rewrite. *** 2026-07-20 Mon @ 16:35:00 -0500 Extracted validate_yesno and the NVIDIA_MIN_DRIVER constant @@ -2386,42 +2282,6 @@ The maintenance console's coredump metric flagged telega-server on ratio (8 core * Archsetup Resolved -** DONE [#C] Net panel: Enterprise error never dismisses :bug:dotfiles:network: -CLOSED: [2026-07-12 Sun] -Fixed in dotfiles =a157bed=. Root cause: error toasts are sticky by design (so background refreshes can't wipe an unread error), but the enterprise join hint's flow posts no follow-up status and row clicks post none either, so nothing ever replaced it. Fix: a window-wide capture-phase click gesture dismisses a sticky toast on the user's next interaction; policy in =viewmodel.toast_action_plan= (unit-tested), timed toasts and background clears unchanged. Panel smoke run confirms launch/doctor/close with the gesture installed. Pointer-level dismiss is a manual-testing child (AT-SPI can't drive pointer gestures). Repro screenshot: =~/pictures/screenshots/2026-07-10_195911.png=. -** DONE [#C] Net diagnostics leak connection names + SSIDs into copyable report and --json :bug:dotfiles:network:solo: -CLOSED: [2026-07-12 Sun] -Resolved in dotfiles =df1543a=: the =redact_ssid= toggle now scrubs saved profile names, active SSIDs, envelope-carried names, and =.nmconnection= keyfile basenames from the copyable report and the diag/doctor =--json= envelopes (one systemic pass in =redact.py=; MAC/IP scrub applies to those envelopes too). On-screen output and functional envelopes (status/list) unchanged. 15 new tests; live-verified on ratio (toggle on removes the active connection name from =diagnose --json=, default unchanged). -The net doctor's copyable report (=report.py=, =scrub_text=) scrubs only MAC/IP, and =net diag/doctor --json= (=cli.py=) dumps the raw dict with no redaction. SSID redaction lives only in the event log (=redact_event=, gated on =redact_ssid=, default off). So a connection name (usually the SSID) appears in the clear in the link-step evidence and in every =--json= consumer — the copyable report is exactly the text a user pastes into a bug report. Secrets (PSK/password/token/portal URL) are already stripped, so this is names, not credentials: Minor severity, graded on severity alone per the privacy carve-out. - -Split out of the 2026-07-11 net-doctor-expansion spec review: that spec's new rival-manager/keyfile-perms verdicts keep parity with this pre-existing behavior rather than half-solve it. Fix shape: extend redaction to cover the connection name + keyfile basename across the copyable report and =--json= (one systemic pass, not per-verdict), with a redaction test. Engine-wide, so it wants one coherent change rather than being bolted onto the expansion work. -** DONE [#B] Bt doctor expansion v1 — build the READY spec :feature:dotfiles:bluetooth: -CLOSED: [2026-07-12 Sun] -:PROPERTIES: -:SPEC_ID: 3d4d61c4-e5df-44e9-b8e0-40b31452c3f7 -:END: -Build the [[file:docs/specs/2026-07-11-bt-doctor-expansion-spec.org][bt doctor expansion]] (IMPLEMENTED). Adds a dmesg firmware-hint probe (names the missing blob on a no-adapter fault) and a boot-enablement probe (catches an adapter disabled at boot) to the shipped bt doctor (=~/.dotfiles/bluetooth/=). Archsetup owns the dotfiles work end to end. All phases shipped and fake-verified (d19fdca, f05a9b4, d7d859f); the live reboot-persistence half is on the manual-testing checklist. -*** 2026-07-11 Sat @ 03:06:32 -0500 Built the two read-only probes -New module =bluetooth/src/bt/probes.py= plus =doctor.py= wiring, on dotfiles main (=d19fdca=, pushed). Two reads the diagnose chain never did: =firmware_hint()= scans the current boot's kernel log for per-vendor firmware-load failures (Intel ibt-*.sfi, MediaTek BT_RAM_CODE, Realtek rtl_bt, Broadcom .hcd, Qualcomm QCA), returning the named blob via a bounded =cmd.run(journalctl -k)= that reuses the =doctor.py:84= precedent; =boot_enablement()= reads three boot-persistence signals (bluez AutoEnable from main.conf [Policy], =systemctl is-enabled bluetooth=, whether TLP lists bluetooth in =DEVICES_TO_DISABLE_ON_STARTUP=). =diagnose()= gates the firmware read to the no-adapter branch and the boot read to the soft-blocked/powered-off branch, so a healthy run reads neither; the raw signals ride a new =probes= key that =doctor()= carries into =--json=. Detection only: no verdict, formatter, or repair change (that's Phase 1). Every read degrades to None on an unreadable tool/file, so a probe that can't see never invents a fault. AutoEnable absent/unset reads None, not false, matching bluez's compiled default of true, so only an explicit =AutoEnable=false= is the fault. New env roots for tests (=BT_MAIN_CONF=, =BT_TLP_CONF=, defaulting to absent temp paths in the Sandbox base so no test reads real /etc); =fake-journalctl= branches on =-k=, =fake-systemctl= answers =is-enabled bluetooth=. 125 bt tests, full =make test= green; =/review-code= approved (no Critical/Important; one Minor noting the firmware read also covers the btctl-unavailable branch, harmless). Inbox note sent to dotfiles. -*** 2026-07-11 Sat @ 03:16:59 -0500 Built the firmware-hint Guide verdict -On dotfiles main (=f05a9b4=, pushed). The no-adapter step now names the blob: a new =_no_adapter_step= consults =probes.firmware_hint()= on a genuine no-adapter fault and, on a per-vendor signature match, sets =evidence= to "no Bluetooth adapter found — <Vendor> firmware <blob> failed to load" and =next_action= to "update linux-firmware and reboot", tagged with a new =code="no-adapter-firmware"= so a =--json= consumer can branch without string-matching. A clean log keeps the generic hardware/driver verdict. A Guide, not a repair: the step carries no =repair= action, so =--fix= never touches it, and it needs no privilege model (so Phase 1 lands independently of the shared cross-panel model). A missing =bluetoothctl= (=BtctlError=) short-circuits before the firmware read, so the verdict fires only on a real no-adapter fault, not a broken install — this also tightened Phase 0 (which read the log on both None branches) to the genuine no-adapter case. =_mk= gained a uniform =code= key (default None) added to every diagnose step, mirroring the existing =repair= key; no test asserts an exact step key-set, verified. =format_doctor_human= already renders =evidence=/=next_action=, so no formatter change. 133 bt tests (+8), full =make test= green; =/review-code= clean. Inbox note sent to dotfiles. -*** 2026-07-11 Sat @ 06:48:21 -0500 Built the persistent-power verdict + fix -On dotfiles main (=d7d859f=, pushed). =_powered_step= consumes the bt Phase 0 boot-enablement probe: AutoEnable explicitly false, service disabled at boot, or TLP listing bluetooth → =powered-off-persistent= (code + evidence naming the cause) carrying the =persist-power= repair; absent/unset config reads as auto-enable-on (bluez default) → the plain =power-on=, so healthy machines can't false-positive. The =persist-power= repair fixes only the causes set (AutoEnable=true, =systemctl enable bluetooth=, drop bluetooth from the TLP list), powers the adapter on now, and verifies each cause cleared. Config edits are pure idempotent text transforms in a new =bootconf= module (comments preserved), staged and installed via a fixed-destination =cp= verb so the write needs root but the mutation is unit-testable. =priv.py= gained three narrow verbs (=enable-bluetooth=, =write-main-conf=, =write-tlp-conf=). The repair is Privileged and resolves through =panelkit= before running: can't-elevate degrades to the guide. The bt shim gained =panelkit= on its path. 287 bt tests + 65 make-test suites green, review-code Approve, voice. Inbox note sent. Live half (real reboot persistence) is the VM/manual checklist. -*** 2026-07-12 Sun @ 09:14:00 -0500 Flipped the bt spec to IMPLEMENTED and logged the vNext items -Spec status heading now IMPLEMENTED (dated history line + Status mirror); all four phase headings DONE. vNext items (stale-bond signature, connection-parameter hints, bt-audio-profile expansion) logged as the "Bt doctor vNext" task. The live half (real reboot persistence) remains on the manual-testing checklist — findings there come back as bugs. -** DONE [#B] One copy + close control pair on every output wall :feature:dotfiles:solo: -CLOSED: [2026-07-12 Sun] -Resolved in dotfiles =dccd744=: every wall carries the o-copy/o-clear overlay pair. bluetooth gained the copy key (transcript via the new =viewmodel.step_copy_line=, CLI-shaped); maint traded its header COPY key for the overlay pair, kept HIDE, and its ✕ clears the session log via =PanelModel.wall_clear=; the four hand-rolled wl-copy calls collapsed into =panelkit.clipboard.copy_text= (PANELKIT_WLCOPY test seam), moving maint off the GTK clipboard so its copies survive the panel closing too. 15 new tests (8 clipboard, 4 step_copy_line, 3 wall_clear); full suite 66 green; all four panel smokes run live off-workspace — maint + audio fully pass, net + bt fail only the pre-existing state-word startup race. - -Converge all four instrument-console output walls on the net panel's well controls: a copy glyph and a ✕ close, as an overlay at the top right, hidden until content lands. Craig's call, 2026-07-10, while reviewing the audio doctor's wall: "network panels as standard across all others, make it consistent." - -Where they stand today, no two alike. net has copy + ✕ (=net/src/net/gui.py=, the =o-copy= / =o-clear= overlay). bluetooth has ✕ but no copy. maint has COPY + HIDE as keys in a header row, and no ✕. audio just gained copy + ✕ (dotfiles =bd33440=). - -Work: give bluetooth a copy key, give maint the overlay pair, and lift the four hand-rolled =_copy_output= implementations into one shared helper rather than a fifth copy. maint keeps HIDE alongside close, because its wall is a persistent session action log you collapse and keep, where net's, bt's, and audio's are per-run results you dismiss. - -Copy text is per panel but one rule: it pastes as that panel's CLI prints, so the paste lines up with the terminal a user is already looking at. audio's =viewmodel.wall_copy_text()= is the worked example. - -Consistent with the 2026-07-07 scope note on the sibling task above: net's compact glyph overlay is what standardizes, not maint's wide COPY-key header row. ** DONE [#C] Org-capture float popup grows too large :bug:hyprland:quick:solo: CLOSED: [2026-07-14 Tue] :PROPERTIES: @@ -3589,3 +3449,251 @@ Still open, and why this stays a task rather than closing with the fixes: the he - =write_conf= *truncates* rather than merges, so any hypridle key the renderer does not know about (=ignore_dbus_inhibit=, =ignore_systemd_inhibit=, =inhibit_sleep=, =on-lock=, =on-unlock=) is deleted rather than preserved. That is the largest hole: a key nobody has added yet would vanish the first time a stage is parked. Options: have the renderer preserve the existing general block and unknown keys instead of emitting its own, or accept the template as the single source and move every hypridle setting into the panel. A design call for Craig, and the truncation half is the part that will bite next. +** DONE [#C] hypridle.conf is generated per-machine but tracked :refactor:dotfiles: +CLOSED: [2026-08-14 Fri] +:PROPERTIES: +:CREATED: [2026-08-14 Fri] +:LAST_REVIEWED: 2026-08-14 +:END: +Fixed in dotfiles 83ae7aa. The render is untracked and gitignored; the +store is the only source of truth; hypridle-start renders at session start +and owns the fallback ordering. Both machines reconciled and re-stowed: +velox's tree is clean for the first time today and still carries its own +policy (dim 5, lock 10, suspend-then-hibernate 30), ratio's config is +byte-unchanged. +=hyprland/.config/hypr/hypridle.conf= is rendered by the settings panel +from each machine's own stage config, and it is also a tracked file stowed +to every machine. So a machine whose idle policy differs from the +committed default carries permanent working-tree dirt, and every pull +there needs a stash/pop dance (velox, twice on 2026-08-14). Worse, the +committed copy is whichever machine last committed it, which is how a +desktop ended up tracking a laptop's suspend-then-hibernate line. +Options to weigh: gitignore the rendered file and track only a template or +the stage defaults; render to a non-stowed path and have hypridle read +that; or keep it tracked but commit a machine-neutral render. The first +looks right — the store already holds the real source of truth, and the +rendered file is a build artifact. +** DONE [#B] Podman API socket and camera-passthrough udev rule :feature:solo: +CLOSED: [2026-08-09 Sun] +:PROPERTIES: +:CREATED: [2026-08-07 Fri] +:LAST_REVIEWED: 2026-08-07 +:END: +Shipped 2026-08-09: the installer enables the rootless podman socket at +install time (enable_user_service grew a wants-target arg so socket units +land in sockets.target.wants) and ships +=72-usb-passthrough-cameras.rules= — numbered below 73 per the winvm +rule-ordering correction, GROUP/MODE as the verified grant, uaccess tag kept. +Applied live on ratio (socket enabled+active, 99- file retired, udev +reloaded); velox apply rides the velox-return riders on the sleep/suspend +task. The uaccess-alone hypothesis stays untested until a camera is attached. +From winvm 2026-08-07 (ratio). Two one-time machine-level setups, both live on +ratio and absent on velox; full evidence and rationale in +[[file:docs/design/2026-08-07-podman-socket-and-camera-udev.md]]. + +- Enable the rootless podman socket at install time + (=systemctl --user enable --now podman.socket=). Socket-activated, zero idle + cost; every podman GUI/API client needs it, and its absence fails silently + (Pods opens to an empty window). The installer already carries the + "=systemctl --user enable= fails during install" workaround pattern + (=archsetup:1270=, =:2722=) — use it. +- Ship a udev rule granting GROUP="video", MODE="0660" on the OBSBOT + (3564:ff02) and BRIO (046d:085e) USB nodes so =usbredirect= can claim them + for VM passthrough. CORRECTED (winvm, 2026-08-08): the original "uaccess + can't ACL raw USB nodes" claim was wrong — the mechanism is rule ordering. + The ACL is applied by =73-seat-late.rules=, so a =99-= rule adds the tag + after that already ran; distro rules that add the tag all sort at or below + 70. [@70] So number our file below 73 (e.g. =72-usb-passthrough-cameras.rules=), + keep the verified GROUP/MODE grant, and keep the tag — correctly ordered it + may make uaccess work on its own (untested hypothesis; a tighter grant if + it holds, needs the camera plugged in to verify). Reconcile ratio's + existing =99-= file (winvm installed it) when the installer version lands. + +Scope: installer step + rule file + tests per existing shapes, and apply both +live to velox over tailscale (daily-driver sync — neither exists there today). +:PROPERTIES: +:CREATED: [2026-07-28 Tue] +:LAST_REVIEWED: 2026-07-28 +:END: +Craig, from the roam inbox 2026-07-28: "launching into wayland doesn't honor previous caffeine settings ...or I expect any other settings in the desktop settings module." Captured right after the 08:59 reboot. + +Confirmed, and it generalizes past caffeine. The settings module splits cleanly into two halves, and only one of them persists. + +Persisted, in =~/.config/desktop-settings/state.json= (=store.py= =DEFAULTS=): program slots, idle-tripper stages, wallpaper. These come back correctly. + +Not persisted — every one is derived live from a process or a compositor runtime option, so a session restart resets it to whatever =hyprland.conf= establishes: +- Caffeine — =caffeine_state()= is =pgrep -x hypridle= inverted, and =hyprland.conf:73= runs =exec-once = pkill -x hypridle; hypridle=. So every launch unconditionally starts hypridle, which means caffeine is *always* OFF after login. There is no code path that could restore it ON. +- Auto-dim — =dim_state()= reads =hyprctl getoption decoration:dim_inactive=, a compositor runtime value that resets to the config default on restart. +- Night light — =state()= is =pgrep -x gammastep=; the process dies with the session. +- DND — =dunstctl=; dunst restarts fresh from =exec-once=. +- Power profile / brightness — owned by powerprofilesctl and systemd-backlight, outside this module's scope. + +Verified live 10 minutes after the reboot: hypridle running (caffeine OFF), dim =false=, gammastep not running, dnd =false=, power =balanced=. Every toggle sat at its factory position. + +The failure is silent, which is what makes it bite: nothing tells you the value you set was discarded. That is the mechanism behind the 2026-07-27 lockout, where Craig believed caffeine was on and the screen locked anyway. + +Grading: Major severity (the panel's core promise is holding these values, and the reset is silent and total across all four toggles) x most users frequently (every session start resets them, though it only harms when a deliberate non-default was set) = P2 = [#B]. + +Not :solo: — the fix needs Craig's call on *which* toggles should persist and whether persistence is per-toggle opt-in. Restoring night light at 3pm or caffeine on a laptop are both plausibly wrong, so this is a preference question, not a derivable one. The mechanism itself (extend =store.py= with a =toggles= block, restore on session start) is mechanical once that's settled. + +Related: =[#B] Caffeine state is unreadable on both surfaces= covers display accuracy — whether the surfaces report the truth. This covers whether the value survives at all. Distinct bugs, same subsystem. + +*** Side finding — gammastep loses a startup race and nothing relaunches it +=hyprland.conf:75= runs =exec-once = gammastep=, but no gammastep process is alive. Today's three launch logs tell the story: =gammastep-2026-07-28-090034.log= carries "Wayland connection experienced a fatal error: -1 / Temperature adjustment failed", and the other two are empty. + +Launched by hand afterward it runs fine and survives, so gammastep is not broken — it loses a race against compositor readiness at session start. Nothing relaunches it, so night light is simply off for the whole session, silently. (An earlier read of this said night light "has likely never worked from the config". That was wrong: the failure is a startup race, not a permanent break.) + +Worth its own task — the fix is a readiness wait or a retry around that exec-once, not a persistence change. Filed here for now because it surfaced during this investigation. +** DONE [#A] Comet KVM setup for truenas :feature:infra:truenas: +CLOSED: [2026-08-08 Sat] +:PROPERTIES: +:CREATED: [2026-07-27 Mon] +:LAST_REVIEWED: 2026-07-27 +:END: +Resolved: Craig wired up and configured the Comet himself, confirmed working +2026-08-08. The ATX power-board follow-up (hard power-cycle for a truly wedged +box) remains unfiled — raise it if the next outage shows the KVM alone isn't +enough. +Wire up the GL.iNet Comet (GL-RM1) IP KVM against truenas. It was bought 2026-01-14 for exactly this job and its KB node still reads "Arrived, not yet set up." + +Why now: truenas went dark 2026-07-24 and stayed unreachable. Diagnosis from ratio on 2026-07-27 — no tailnet contact for 3 days, 100% packet loss on 192.168.86.5, ARP entry FAILED (nothing answers ARP for the address, so the NIC is down at layer 2), every service port closed, while the gateway and a dozen other LAN hosts stayed reachable. Wake-on-LAN to 70:85:c2:db:9d:94 drew no response. With no console and no out-of-band power control there was no remote remedy at all, so recovery needed hands on the box. The Comet closes exactly that gap: BIOS/UEFI console, Wake-on-LAN, and browser access over its native Tailscale integration. + +Not :solo: — the physical cabling is Craig's, and the Tailscale enrollment needs his account. + +Steps, from the KB node ([[id:67bc5994-a763-48e2-926f-4ac0d1bad3db][GL.iNet Comet (GL-RM1) - KVM]]): +1. HDMI from truenas video out to the Comet's HD IN. +2. USB-A-to-USB-C from the Comet to a truenas USB port (keyboard/mouse emulation). +3. Ethernet to the network. +4. Power via USB-C (5V/2A). +5. Reach the web interface and enroll it in Tailscale, so it's usable when the LAN side of truenas is the thing that's broken. + +Then verify while truenas is healthy, rather than discovering the gaps during the next outage: confirm the console shows POST and the BIOS, that keyboard input reaches the box, and that Wake-on-LAN from the Comet actually powers it on. Enable WOL in the truenas BIOS if that last check fails — this outage never established whether it was on. + +Worth considering as a follow-up: the ATX power board accessory gives hard power-cycle control for a truly wedged box, which the KVM alone can't do. +** DONE [#A] Review post-archsetup laptop setup steps (velox 2026-04-10) +CLOSED: [2026-08-08 Sat] +:PROPERTIES: +:LAST_REVIEWED: 2026-08-08 +:END: +Closed at the 2026-08-08 session: every open item got its automate-vs-document +call and the work landed the same night (tests green, committed). Residual: +velox itself still needs the new tlp.d radio line and a dotfiles pull — folded +into the [#A] sleep/suspend task, which works the same files on velox anyway. +Items discovered during velox setup that needed manual intervention after archsetup. +Decide which should be automated in archsetup vs documented as post-install steps. + +*** 2026-08-08 Sat @ 04:43:42 -0500 Automated radio enable via TLP (rfkill boot soft-block) +Root cause sharpened during triage: archsetup masks systemd-rfkill on laptops +(it fights TLP), so nothing restored radio state at boot — the "unblock once +should stick" premise was wrong under the mask. Fix in the TLP custom conf: +=DEVICES_TO_ENABLE_ON_STARTUP="bluetooth wifi"=, the TLP-native mechanism. +configure_tlp_power parametrized for tests; covered by +tests/installer-steps/test_configure_tlp_power.py. + +*** 2026-07-04 Sat @ 11:48:24 -0500 Automated /efi restrictive mount permissions in fstab generation +archsetup:2827-2836 now rewrites the /efi fstab line to =fmask=0177,dmask=0077= (idempotent), so fresh installs no longer land the world-accessible =fmask=0022,dmask=0022= default. Confirmed via the 2026-07-04 task audit. (Original velox note: default vfat mount had =fmask=0022,dmask=0022=, hand-fixed to restrictive; bootctl warned about a world-accessible random-seed file.) + +*** 2026-08-08 Sat @ 04:43:42 -0500 Automated tmp.mount mask for ZFS /tmp +New mask_tmp_mount_for_zfs, called from configure_snapshots' ZFS branch: +masks tmp.mount only when the pool actually carries a dataset mounted at +/tmp (exact match), silent no-op without zfs or without the dataset. Covered +by tests/installer-steps/test_mask_tmp_mount_for_zfs.py; the orchestrator +dispatch pin updated. + +*** 2026-08-08 Sat @ 04:43:42 -0500 Automated CPU microcode install by vendor +New install_cpu_microcode, first in boot_ux so grub-mkconfig and mkinitcpio's +microcode hook both see the installed /boot/<vendor>-ucode.img: vendor_id from +/proc/cpuinfo → intel-ucode / amd-ucode, error_warn on unknown vendor. +Covered by tests/installer-steps/test_install_cpu_microcode.py; boot_ux +sequence pin updated. + +*** 2026-07-04 Sat @ 11:48:24 -0500 Automated syncthing user-service enable in archsetup +archsetup:2263-2271 now installs syncthing and enables the user service (via symlink), so fresh installs no longer leave it installed-but-disabled. Confirmed via the 2026-07-04 task audit. (Original velox note: package installed but service not enabled; hand-fixed with =systemctl enable --now syncthing@cjennings=.) + +*** 2026-08-08 Sat @ 04:43:42 -0500 Closed the awww-daemon crash watch — no recurrence +The April boot crash never recurred across four months of daily use on both +machines (and the wallpaper stack has since been reworked). Reopen as its own +bug with fresh evidence if it ever comes back. + +*** 2026-08-08 Sat @ 04:43:42 -0500 Automated touchpad device detection in the pointer scripts +The scripts were already in stowed dotfiles with binds — the open half was the +hardcoded Framework device name. Both touchpad-auto and toggle-touchpad now +auto-detect the touchpad (first pointer named *touchpad*, pixa fallback) and +derive the internal-pointer exclusion set from the detected name, so they +agree on any machine. Test seams added (--detect / --has-external-mouse); +tests/touchpad-auto/ new, toggle-touchpad suite still green. Dotfiles commit; +velox picks it up on its next pull. + +*** 2026-08-08 Sat @ 04:43:42 -0500 Documented bluetooth pairing in the post-install checklist +Inherently interactive, so it can't ride the installer. Documented in the new +[[file:docs/post-install-checklist.org][docs/post-install-checklist.org]] along +with the Proton Bridge steps — the standing home for manual post-install work. +Consider: document as post-install step. No automation possible. + +*** 2026-05-26 Tue @ 13:32:31 -0500 pocketbook install concern moot — pulled from publication, folded in-tree +Resolved by removing pocketbook from archsetup's provisioning entirely. It's nowhere near ready, so the github mirror + cjennings.net repo were deleted and the project was folded into the archsetup tree at =pocketbook/=. Dropped the =gtk4-layer-shell= dep + =pip_install= from =archsetup= and the clone from =scripts/post-install.sh=. No fresh install pulls pocketbook now, so "not installed on velox" no longer applies. Re-wiring the install is tracked in the new pocketbook development backlog. + +*** TODO Review: Tailscale needs login after install +~tailscaled~ service was enabled but needed ~tailscale up~ for interactive auth. +Old machine entry needed cleanup in admin console. +Consider: document as post-install step. + +*** TODO Review: docs/ directories need manual sync from existing machine +docs/ dirs (gitignored) for ~/code and ~/projects repos needed scp/rsync from ratio. +Same for ~/.emacs.d/docs/. Not in git, so not available after clone. +Consider: document as post-install step or create a sync script. +** DONE [#C] Waybar modules run together — need subtle separators :bug:dotfiles:waybar: +CLOSED: [2026-08-08 Sat] +Closed at the 2026-08-08 task review: Craig confirms the separator work landed +a while back and the bar reads correctly now. +Craig misreads where one module ends and the next begins — the wind (weather) value runs straight into the date with no visual stop, so he reads the wind figure as the start of the date. Add a light, subtle separator or spacing between adjacent Waybar modules. +Grading: Minor severity (legibility, nothing broken) x frequent (every glance at the bar) = P3 = [#C]. +Not fully :solo: — needs Craig's eye on the result (separator style is a taste call, plus a live visual check). Prior work added a date-facing divider (dotfiles 103cccb); evidently not enough, so revisit the whole inter-module treatment rather than just the weather/date seam. From .emacs.d handoff 2026-07-20-1114 (roam capture; waybar is archsetup-owned per the dotfiles standing rule). +** CANCELLED [#C] Add a whole-display dim mode :feature:hyprland: +CLOSED: [2026-08-08 Sat] +Killed at the 2026-08-08 task review: the July auto-dim work covers the actual +need; no separate dim-everything mode wanted. +Extend auto-dim with an explicit “dim everything” setting for bright +non-dark-mode contexts, with a security/usability review of its scope. +** DONE [#C] Fix install errors surfaced by the 2026-05-11 VM test run +CLOSED: [2026-08-08 Sat] +:PROPERTIES: +:LAST_REVIEWED: 2026-07-06 +:END: +Closed at the 2026-08-08 task review: every archsetup-attributable error was +fixed and verified (fontconfig, dconf x2, emacs-stow, AUR exit-0 logging at +the root); the residual four reproduce unchanged and are diagnosed +environment/non-critical, with two 2026-06-28 full runs attributing zero +issues to archsetup. Residual thread: confirm the firewall nf_tables pair on +bare metal at the next real install — no container task needed to carry it. +*** 2026-06-28 Sun @ 13:29:29 -0400 Audit reconcile: 2026-06-28 btrfs+zfs runs reproduce the same residual set +Newer full runs landed since the 2026-06-11 reconcile below: the 2026-06-25 zfs run (Testinfra 96/0) and the 2026-06-28 btrfs+zfs runs (97/0, "zero attributed issues"). The residual four were NOT fixed and reproduce unchanged: =enabling firewall= (archsetup:1496-1498, carries a VM-kernel note), =enabling gamemode for user= (archsetup:2221, non-critical), and =tidaler (AUR)=. Zero archsetup-attributed Testinfra issues across both profiles confirms these are environment / non-critical, not archsetup bugs. Bare-metal confirmation of the firewall pair is still the open thread. + +*** 2026-06-15 Mon @ 23:53:21 -0500 Audit reconcile: latest VM run (2026-06-11) confirms the surviving error set +The most recent VM run (=test-results/20260611-113904/=) carries four error-summary entries: =enabling firewall= + =verifying firewall is active= (the iptables/nf_tables "Could not fetch rule set generation id" pair, still unconfirmed on bare metal), =enabling gamemode for user= (non-critical), and =tidaler (AUR)=. The earlier fontconfig/dconf fixes held — none reappear. So the count is down from the 7→6 anchor below to four, all of them the known-residual items already itemized. +Errors logged during the VM install. Status as of the 2026-05-11 18:36 run (=test-results/20260511-183643/archsetup-output.log=) after the =48c9439= fontconfig/dconf fix: 7 → 6. +- refreshing font cache — RESOLVED in =48c9439= (now installs =fontconfig= before calling =fc-cache=). +- configuring GTK file chooser — RESOLVED in =ecab29f= (switched to a system-wide dconf db at =/etc/dconf/db/site.d/=; needs no session bus during install). +- configuring GNOME interface settings in dconf — RESOLVED in =ecab29f= (same fix as the GTK file chooser above). +- enabling firewall — exit 1: =iptables v1.8.13 (nf_tables): Could not fetch rule set generation id: Invalid argument=. Still present in the 18:36 run; likely a VM-kernel/nf_tables artifact — confirm on bare metal before treating as an archsetup bug. +- verifying firewall is active — exit 1 (follow-on from the firewall-enable error). +- enabling gamemode for user — exit 1 → step "gaming" FAILED — non-critical. +- tidaler (AUR) — logged in the error summary with exit code 0 (odd; logging quirk or transient AUR build noise?). +Also seen in the 18:36 run's log-diff (post-install systemd noise, probably VM-environment): =pam_systemd … CreateSession failed= / =logind: Failed to start session scope … Permission denied=, and =Failed to start Proton VPN Daemon= (no VPN config in the test VM). + +*** 2026-05-19 Tue @ 13:18:56 -0500 Fixed AUR exit-0 logging bug at the root +Root cause was in =retry_install=: =last_exit_code=$?= ran AFTER =if eval ...; then return 0; fi=. Bash defines an if-compound's exit status as zero when no condition tested true, so a failing eval's exit code got overwritten with 0 before reaching =error_warn=. Fix in =8221c54=: capture =$?= from =eval= directly into a local var, then compare against the captured value in the if. VM-verified in =test-results/20260519-115318/=: =mkinitcpio-firmware (AUR)= and =tidaler (AUR)= now report =error code: 1= (yay's actual exit) instead of the misleading =error code: 0=. The same packages still appear in the summary because yay returns non-zero when sub-deps fail to build (e.g. =aic94xx-firmware=), but the codes are accurate now. If the underlying sub-dep failures stay noisy, that's a separate concern — open a new task. + +*** 2026-05-16 Sat @ 09:00:41 -0500 AI Response: Surfaced the expanded AUR-exit-0 pattern +2026-05-16 07:40 VM run passed (52/0/5) with the same warning profile as the 2026-05-11 18:36 run. Error count went 7 → 13: 5 fixed/unchanged, +5 new AUR-exit-0 entries (broadens the existing tidaler item into the dedicated =[#B]= subtask above), +1 genuinely new error in =setting up emacs configuration files= (=git pull= ran in =~/.emacs.d= which existed from stow but had no =.git=). Patched =archsetup:1932-1945= with a three-branch check: clone if missing/empty, pull if =.git= exists, =git init=/=fetch=/=checkout= in place if the dir came from stow. + +*** 2026-05-19 Tue @ 01:25:26 -0500 Verified the b9907c7 emacs-stow fix end-to-end +=make test= 21:44 → 22:29 (42 min), =test-results/20260518-214516/=. 52/0/5, =ArchSetup Exit Code: 0=. The third-branch path fired correctly — install log =archsetup-2026-05-18-21-45-46.log:14358-14365= shows =From https://git.cjennings.net/dotemacs= → =[new branch] main -> origin/main= → =Reset branch 'main'= → =branch 'main' set up to track 'origin/main'=. No exit-128, no =fatal: not a git repository=. Error Summary down to 7 (was 13 on 2026-05-16); the emacs entry is gone. AUR exit-0 logging triggered for 2 packages this run (mkinitcpio-firmware, tidaler) vs 6 on 2026-05-16 — same bug class, fewer triggers, still tracked under =[#B] AUR exit-0 logged as error=. Issue Attribution: 1 ARCHSETUP entry (Proton VPN Daemon failed — known VM-no-VPN-config artifact). Cleanup ran clean via the normal path. +** CANCELLED [#C] Review current tool pain points annually +CLOSED: [2026-08-08 Sat] +:PROPERTIES: +:LAST_REVIEWED: 2026-07-06 +:END: +Killed at the 2026-08-08 task review: an undated annual intention that never +fired — pain points get surfaced organically as they bite. +Once-yearly systematic inventory of known deficiencies and friction points in current toolset |
