diff options
Diffstat (limited to 'todo.org')
| -rw-r--r-- | todo.org | 122 |
1 files changed, 110 insertions, 12 deletions
@@ -45,41 +45,98 @@ below): input-side-spec.org (DRAFT, four decisions open). * Archsetup Open Work +** DOING [#B] Build: desktop-settings panel :feature:hyprland:dotfiles: +:PROPERTIES: +:SPEC_ID: d6bb1e73-ec90-4327-85ee-bfa762da5bce +:END: +The GTK build of the desktop-settings panel per the spec (docs/specs/2026-07-02-desktop-settings-panel-spec.org, DOING; normative reference: prototype 37). Work happens in dotfiles settings/ — archsetup drives the lifecycle. Two non-blocking build-time picks live in the spec's Review findings (wallpaper setter tool; store location/format) — decide in phase 1 and record there. +*** 2026-07-22 Wed @ 13:14:01 -0500 Built the backings engine (phase 1) — dotfiles 7a15237 +Landed as dotfiles settings/src/settings (10 modules) + tests/settings (118 tests against fake binaries, auto-discovered by make test — 81 suites green). Covers brightness/kbd (5% floor, x10 drum), toggles (dim, pointer cycle via toggle-touchpad, caffeine), DND class-split (dunst pause level 60, close-all before unpause, alarms punch through live), powerprofilesctl, nightlight (resident gammastep), hypridle.conf renderer + symlink-safe write + caffeine-respecting reload + hyprlock grace, suntimes (pure NOAA math), and the wallpaper engine (awww/mpvpaper/projector adapters, galleries, random draw, atomic JSON store). All three build-time picks recorded as DONE findings in the spec (setter=awww, store=state.json, nightlight=gammastep). Handoff note in ~/.dotfiles/inbox/. +*** TODO Phase 2 — presenters :solo: +GTK-free models at 100% unit coverage: program matrix (complete definitions, active-is-live surviving member writes, pin/letter/radio rows, slots 1-4), bench (drums, pointers, idle clamping/parking/bypass), wallpaper channels (mint/edit/delete/sort for pairs/sets/colors, per-mode sources, previews). +*** TODO Phase 3 — GTK4/Blueprint UI +Port prototype 37's instruments to GTK in family chrome: console keys, programmable matrix, drum roller, tripper dial (bottom legend, exact drag counter, bypass stamp), encircled groups, iconic channel cards, themed gallery wells, the three presses. Self-clocked instruments own their widget lifetime. Layer-shell chassis, sub-view navigation, AT-SPI smoke. +*** TODO Phase 4 — integration and bar +Bar consolidation LANDED EARLY (2026-07-22, live): gear module + Super+Shift+G wired; dim AND caffeine modules dropped (Craig amended decision A during the first drive — bar keeps only touchpad; dim/caffeine are panel-owned, keybinds stay). Remaining: watch/clock/world projected renderers (night watch as the hyprlock face); live hypridle rewrite; dunst pause-level config (alarm rules with override_pause_level 100); refresh-signal rewiring; end-to-end verify-everything. +Backing tools: mpvpaper (AUR) + power-profiles-daemon installed on ratio 2026-07-22 and added to the installer (ppd service enable gated on no-battery, since TLP owns power on laptops). Remaining: velox wants mpvpaper (and optionally the ppd package, service off) by hand — one-time AUR install the sync doesn't carry. +*** TODO Test surface — end-to-end pass +A scripted end-to-end pass mirroring prototype 37's 17-point suite against the real panel, plus the per-phase suites called out above. +*** TODO Flip the spec to IMPLEMENTED +When the phases land: flip docs/specs/2026-07-02-desktop-settings-panel-spec.org DOING → IMPLEMENTED with a dated history line naming the shipping commits. +** TODO [#C] Timer module hero hierarchy :feature:waybar:timer: +From the roam inbox (Craig, claimed 2026-07-22). Which display ("hero") wins the waybar timer module when several timer modes run simultaneously: pomodoro wins over everything (the user is actively working; it's likely their main focus). The rest rank in chronological order of when they would ring. Worked example: with a just-started 15-min timer, a 1-hr timer at 10 minutes left, a pomodoro, and an alarm ringing in 12 minutes — show the pomodoro; when it completes, the 1-hr timer (rings first), then the alarm, then the 15-min timer. Feeds the timer-panel spec (docs/specs/2026-07-02-timer-panel-spec.org). +** TODO [#C] Timer module: drop RING message, persistent notifications :bug:waybar:timer: +From the roam inbox (Craig, claimed 2026-07-22). Remove the RING message from the timer module display; verify all timer and alarm notifications are persistent; the icon returns to normal once the notification has fired. Rationale: keeps timers and pomodoros from interfering with one another's displays (pairs with the hero-hierarchy task above). +** TODO [#C] PTT icon outline removal :bug:waybar: +From the roam inbox (Craig, claimed 2026-07-22): the waybar PTT icon should not have an outline. Cosmetic × every-glance = P3 = [#C]. +** TODO [#B] Weather tooltip caching :feature:waybar:weather: +From the roam inbox (Craig, claimed 2026-07-22): retrieve the weather tooltip data once per hour and cache it. If the network is unavailable, display the cached tooltip with explanatory text saying so. Dotfiles-side work (archsetup owns the lifecycle); touches common/.local/bin/weather. +** TODO [#C] WiFi tooltip signal strength :feature:waybar:network: +From the roam inbox (Craig, claimed 2026-07-22): add signal strength to the WiFi tooltip. +** TODO [#C] Night-watch live telemetry :feature:maint: +Craig, 2026-07-21 ("mind. blown."): drive the Dupre Night Watch screensaver (docs/prototypes/2026-07-21-night-watch-screensaver-prototype-1.html, the idle-pipeline eye-candy stage in the desktop-settings spec) with real system data instead of synthetic signals — a passive status wall while the machine idles. Candidate mappings: scope = CPU load trace, drift chart = memory pressure history, spectrum = per-core utilization, VU pair = net throughput up/down, blinkenlights = disk I/O, tape counter = uptime, systems lamps / annunciator = maint status verdicts, engine-order telegraph = current power profile, VFD wire = maint status one-liner (temps, battery, pending updates). Browser prototype can poll a small local JSON endpoint; the production shape belongs to the idle-stage build. Depends on the spec's idle-pipeline implementation landing first. +** TODO [#B] Dupre Kit merge — casting additions :feature:tooling: +Fold docs/prototypes/dupre-kit-additions.js back into the kit proper: detentFader (NEW — multi-detent slide attenuator with speedbump drag physics: magnet + escape hysteresis, parked tick glow) and the drumRoller redefinition (UPGRADE — 1..N channels and min/max range; stock hardcodes two drums and throws on one, defaults reproduce stock exactly) and the guardedToggle redefinition (UPGRADE — lever throws with rotateX so it flips toward the viewer instead of the stock 180° planar spin that sweeps sideways mid-transition; contract unchanged). Merge means: builders into widgets.js, the additions CSS into DUPRE_CSS, additions-scoped gradients into the shared defs plate, gallery cards for both in panel-widget-gallery.html, and POLICY entries. Origin: the desktop-settings casting sitting 2026-07-21 — Craig's direction is that components get finished by being needed ("the ones needed most will have had the most attention"), so more additions may accrue here before the merge; batch them. +** TODO [#C] Wlogout screen review :bug:hyprland:dotfiles: +Craig, 2026-07-21: the wlogout window (Super+Shift+Q — lock/reboot/shutdown/logout/suspend/hibernate) "isn't great and has bugs." Review it end to end: catalogue the specific bugs, then assess the design against the Dupre instrument-console family (it predates the panel aesthetic). Config lives in dotfiles; the bind is hyprland.conf:428 (=pgrep -x wlogout || wlogout-menu=). Context: the desktop-settings panel spec withdrew lock/suspend in favor of this screen (2026-07-21 amendment), so it's now the sole owner of session-exit actions — worth being good. Grade each bug found via the severity×frequency matrix; this parent stays a [#C] review until specifics emerge. ** TODO [#B] Audit cgit-published repos for secrets and privacy :bug:security: +:PROPERTIES: +:LAST_REVIEWED: 2026-07-21 +:END: Grading: security carve-out — cgit at git.cjennings.net serves every repo under scan-path=/var/git over unauthenticated https (any repo is anonymously cloneable). archsetup being public is by design (curl-install), but this means ANY secret in ANY /var/git repo is world-readable, and any repo meant to be private is not. Severity depends on what else lives there = P2 = [#B], raise if a private repo with secrets is found. Not :solo: — needs Craig's decisions. Steps: list repos under /var/git; for each, decide intended public vs private; scan each for secrets (keys, tokens, credentials) the way this WireGuard leak was found; for any meant-to-be-private repo, actually restrict access (cgit repo.hide only hides from the index — a known repo name is still cloneable; use http auth or move it off the public scan-path); for public repos, confirm no secrets and add a pre-receive/CI secret scan. Check dotfiles (git.cjennings.net/dotfiles) specifically — it is also under /var/git. archsetup's own move is decided and tracked separately below. ** TODO [#B] Move archsetup off cgit to cjennings@cjennings.net :chore:security: +:PROPERTIES: +:LAST_REVIEWED: 2026-07-21 +:END: Decided (Craig, 2026-07-20): move the archsetup repo off the public cgit host (git@cjennings.net, scan-path /var/git) to Craig's private account remote cjennings@cjennings.net, so it is no longer world-cloneable. This is the archsetup-specific fix for the cgit-exposure finding above. Plan: create a bare repo under cjennings's control off the cgit scan-path (e.g. =~cjennings/git/archsetup.git=); push current main + tags there; migrate the post-receive hook that publishes the installer to =/var/www/cjennings/archsetup= so curl-install keeps working (the single published file stays public by design; only the repo goes private); update the origin remote on ratio and velox to =cjennings@cjennings.net:git/archsetup.git=; remove =/var/git/archsetup.git= so cgit no longer serves it. Verify: anonymous =git clone https://git.cjennings.net/archsetup.git= fails, the new private clone works from both machines, and the curl-install URL still returns the installer. Keep the two daily drivers' remotes in sync (daily-drivers rule). ** TODO [#B] Velox boot-failure retrospective — upgrade guard gaps :bug:zfs:maint: +:PROPERTIES: +:LAST_REVIEWED: 2026-07-21 +:END: Post-mortem for the 2026-07-15 velox no-kernel boot failure, from the archsetup/maint code review: - maint's UPDATE remedy runs a plain =yay -Syu --noconfirm= (remedies.py:297). The live-update guard (guard.py) only matches mesa/hyprland (the 2026-06-07 live-swap class) — it never checks /boot, kernel, initramfs, or mkinitcpio exit. No post-upgrade /boot assertion exists. An interrupted kernel transaction slips straight through. - Add a post-upgrade /boot assertion: after a transaction touching linux/linux-*, confirm vmlinuz-* + initramfs-*.img present and mkinitcpio exit 0; refuse to end the run (or page Craig) otherwise. Would have caught this. - Sanoid-vs-actual dataset drift: configure_zfs_snapshots configures zroot/var/log + zroot/var/lib/pacman as separate datasets; velox's actual layout has neither separate (/var/log sits inside zroot/var). Reconcile. -- Confirm the pre-pacman snapshot hook is actually installed + firing on velox (it should be — it's what makes recovery possible). +- CONFIRMED (2026-07-21): the pre-pacman snapshot hook fired on velox — the 2026-07-15 no-kernel boot was recovered via the pre-pacman ZFS snapshot rollback, and velox is back on the tailnet running linux-lts 6.18.38 with initramfs present (2026-07-19 session). Root-cause hook-ordering fix shipped separately. Still open: the post-upgrade /boot assertion in guard.py and the sanoid-vs-actual dataset drift reconcile (the two bullets above). -** TODO [#B] Hyprland layoutmsg crash — bad_variant_access (upstream) :bug:hyprland: +** CANCELLED [#B] Hyprland layoutmsg crash — bad_variant_access (upstream) :bug:hyprland: +CLOSED: [2026-07-21 Tue] +Dropped 2026-07-21 (Craig's call) — not tracking the upstream report. The crash evidence (both reports + tmpfs log excerpts) and the voice-passed issue draft stay preserved in [[file:working/hyprland-layoutmsg-crash/][working/hyprland-layoutmsg-crash/]] if it recurs and is worth reviving. Grading: Critical severity (SIGSEGV kills the whole desktop session; every GUI app's unsaved state lost) x rare edge case (twice in ~4.5 months: 2026-03-07 on v0.54.1, 2026-07-20 on v0.55.4) = P2 = [#B]. Upstream Hyprland bug, not this repo's code — the task tracks reporting it and picking up the fix. A layoutmsg mfact dispatch (layout-resize, mod+H/L) throws std::bad_variant_access inside Layout::CAlgorithm::layoutMsg, uncaught, SIGSEGV. Both crashes fired from the layout-resize mfact path (keycode 104 shrink today, 108 grow in March). Layout at crash was master and the identical mfact had worked seconds earlier; the pre-crash window held monocle<->master toggles, two window closes dropping focus to "[Window nullptr]", and togglefloating x2. Monocle is a registered v0.55 layout (log shows graceful "Unknown monocle layoutmsg" rejects), so the config is not at fault; related edges are guarded ("mfact -> no window") while this path misses its variant guard. Repo has no newer build (0.55.4-1 installed and repo). Evidence preserved in [[file:working/hyprland-layoutmsg-crash/][working/hyprland-layoutmsg-crash/]] (both crash reports + excerpts from the tmpfs session log, extracted before reboot loses it). Next: Craig posts the issue himself (2026-07-20 decision) — the voice-passed draft is [[file:working/hyprland-layoutmsg-crash/issue-draft.md][issue-draft.md]], with both crash reports and the log excerpts beside it for attaching. Watch the repo for a fixed release and close on confirmation. The layout-resize script guard was declined (a script can't observe the internal desync). ** TODO [#B] Assess a Hyprland left-drag window gesture :feature:hyprland: +:PROPERTIES: +:LAST_REVIEWED: 2026-07-21 +:END: Evaluate whether a global left-click drag can move ordinary windows without breaking application selection, text interaction, or Wayland security expectations. Document the safe modifier/gesture alternatives before changing any binding. ** TODO [#B] Reconcile panel keybindings around Super+N :feature:hyprland: +:PROPERTIES: +:LAST_REVIEWED: 2026-07-21 +:END: Swap the notification and networking bindings so primary panels are one Super-plus-letter chord away, audit the other exceptions, and bring the proposed family to Craig for a final mapping decision. ** TODO [#B] Add storage-capacity signals to the maintenance module :feature:maint: +:PROPERTIES: +:LAST_REVIEWED: 2026-07-21 +:END: Investigate capacity and growth diagnostics for full disks, identify the appropriate remedies, and incorporate a clear storage signal into the maintenance console. ** TODO [#B] Add per-channel controls to the audio panel :feature:audio: +:PROPERTIES: +:LAST_REVIEWED: 2026-07-21 +:END: Expose channel-level input and output volume controls without losing the existing device-level workflow. @@ -329,6 +386,8 @@ On dotfiles main (=d73eba6=, pushed). The clean, unambiguous verdict of the thre On dotfiles main (=c9f8604=, pushed). Craig approved proceeding with the default precedence. =classify= adds =disable-rival= (rival dhcpcd/networkd/iwd active + a failing link) and =chmod-keyfile= (bad-perms keyfile + a failing link), both =remedy_class="privileged"= through the same panelkit gate. PRECEDENCE settled: both gate on a local-link symptom (never nag next to a working link), sit behind rfkill/service (more fundamental) and ahead of the generic reset (naming the cause beats a blind reconnect); tested (rfkill beats rival, rival beats reset). Priv verbs =disable-rival= (three-unit allowlist), =chmod-keyfile=/=chown-keyfile= (paths validated under system-connections, no traversal). Repairs re-derive their target (=active_rivals= / the active connection). =fake-systemctl= gained a state dir so a disable flips the re-check. 782 net tests + 65 suites green, review-code clean. Two coverage edges deferred to the VM: the keyfile fix's root-owned pass (only reproduces under root), and whether disable-rival needs a follow-on reset to restore the link. All three Phase 1 verdicts now fake-complete; VM live-verification is the remaining piece (see the sub-task). **** TODO Net Phase 1 live verification — run the scenario harness against a VM The harness is BUILT (archsetup =a364c1e=): =scripts/testing/net-scenarios/{10-nm-masked,20-rival-manager,30-keyfile-perms}.sh= (break/fix/assert + the expected diagnose verdict) and =run-net-scenarios.sh= (rsyncs net+panelkit into a target over ssh, drives the scenarios). Scenario logic reviewed; the ssh transport plumbing is UNEXERCISED (marked first-draft) and wants a shakeout on the first real run. What remains needs Craig: a booted VM (a real kernel + network stack — NM does NOT run reliably in nspawn, so a container only shows the mask-symlink/keyfile-mode half, not "NM active") with NetworkManager + dhcpcd installed, reachable over ssh as root. Then =run-net-scenarios.sh --target root@HOST --profile <saved-profile>=. The two live questions: disable-rival was already chained to a follow-on reset (=be15a81=), so the run confirms whether the reset fires or NM auto-recovers; and the keyfile root-owned pass (only reproduces under root). The by-hand equivalent is the "Manual testing and validation" → "Net doctor privileged fixes" checklist. +***** 2026-07-21 Tue @ 08:20:00 -0500 Decided (Craig): agent runs it via the archangel test VM, deferred to a later session +No longer "needs Craig to provide a VM." The VM is the archangel test harness (=scripts/testing/create-base-vm.sh= + =vm-utils.sh=; ISO in =~/archangel-isos/=). Plan: in a later session the agent boots a fresh archangel VM (NetworkManager + dhcpcd), then runs =run-net-scenarios.sh --target root@HOST --profile <saved-profile>= against it, exercising the unexercised ssh transport on the first real run and answering the two live questions above. A 40-60 min VM operation; agent-driven, checkpointing and surfacing if it needs Craig's hands. This makes the sub-task agent-workable rather than blocked. *** 2026-07-11 Sat @ 06:31:29 -0500 Built the sharpened auth verdict On dotfiles main (=12e3e76=, pushed). =gather_context= derives an auth cause on an auth failure from the saved profile's key-mgmt + the scanned SECURITY flags for the SSID (not GENERAL.REASON, which only marks *that* auth failed): sae / hidden / enterprise / generic. =classify= turns sae and hidden into =fixable= Privileged profile-modifies (=key-mgmt sae= + PMF, or the hidden flag) routed through =panelkit.resolve()= like the Phase 1 control-plane verdicts; enterprise and generic stay =needs-user-action= with a cause-named message. Two new priv verbs (=conn-sae=, =conn-hidden=, uuid-validated single =nmcli connection modify= commands) + =repair_auth_sae=/=repair_auth_hidden=, each chained into a reset (FIX_CHAINS) so NM reconnects with the corrected profile. Hidden fires only on a non-empty scan missing the SSID, so a failed scan can't fabricate it. Tightened the =fake-nmcli= key-mgmt hook to require the =-g= prefix so the conn-sae modify isn't read back as a get_value. Pairwise (reason × profile-state) covered in =TestAuthCauseDerivation=. 813 net tests + 65 suites green, review-code Approve, voice. Inbox note sent. Live half (real WPA3/hidden profile-modify) is the VM/manual checklist. *** 2026-07-12 Sun @ 09:14:00 -0500 Flipped the net spec to IMPLEMENTED and logged the vNext items @@ -379,6 +438,9 @@ Refiled from the archsetup task audit (2026-06-28), landed via ~/.dotfiles/inbox - Review all 50+ scripts in =~/.local/bin= and remove unused ones. - Check dotfiles for uninstalled packages and remove orphaned configs. - Verify all stowed files are actually used. +*** 2026-07-21 Tue @ 08:30:00 -0500 The evidence report's ref counts are UNRELIABLE — redo the scan before any kill pass +Spot-checking the "zero references" list against the live tree during the 2026-07-21 task audit found the report is badly wrong: 12 of a 14-script sample flagged refs=0 are actively invoked. The scan missed the primary invocation paths — =hyprland.conf= =bind=/=exec-once= lines, waybar config =exec=/=on-click= handlers, pypr scratchpad configs, and =profile.d= autostart. Confirmed live examples: =layout-resize= (bound mod+H/L window resize), =net-fix= (waybar net right-click), =start-hyprland= (session launcher, profile.d + startx alias), =wait-for-tray= (exec-once gating signal-desktop tray), =waybar-layout=/=waybar-worldclock= (live waybar modules, worldclock has a test), =stash-window=/=stash-others=/=stash-restore= (bound mod+O family), =hypr-refocus-scratchpad= (exec-once), =monitor-dashboard= (pypr scratchpad on ratio+velox). Only =toggle-scratchpad= and =waybar-disk= came back genuinely unreferenced in that sample. +ACTION before the kill pass: redo the reference scan to grep all invocation sources — =hyprland.conf= (bind/binde/bindm/exec-once/exec), =waybar/config= (exec/on-click*/on-scroll*), =pypr/config.toml=, =profile.d/*=, systemd units, and other scripts — then re-bucket. Nothing was deleted; the current report can't be trusted for deletions. The three orphan config dirs (audacious, wofi, ranger) are independent of the script scan and still stand as candidates. *** 2026-07-14 Tue @ 01:40:48 -0500 Built the audit evidence report Shipped as =docs/2026-07-14-bin-audit-evidence.org= in the dotfiles repo (260752a). 150 scripts bucketed: 69 keep (referenced or cron-driven), 74 kill candidates (zero references in the tree), 7 flagged (all dwm-tier, expected on a hyprland host). Config sweep: audacious and wofi configs are orphan candidates, ranger needs an install-vs-delete call (declared in archsetup but not installed on ratio). Shell history was too shallow (~700 lines) to prove by-hand disuse either way — the kill pass stays Craig's call in the parent task. @@ -1331,6 +1393,8 @@ NOTE (2026-07-04 audit): the "four-tab panel" framing predates the instrument-co :LAST_REVIEWED: 2026-07-09 :END: Remove personal info, credentials, and code quality issues before publishing. +*** 2026-07-21 Tue @ 08:00:00 -0500 Audit reconcile: the four assets/ "& Claude" author lines are fixed +The four =assets/= files the 2026-07-09 note flagged as "Craig's call, still open" all now read =#+AUTHOR: Craig Jennings= (verified). No tracked file outside =todo.org= still carries =Craig Jennings & Claude= (the one in todo.org is a historical dated note quoting the old line). That open item is resolved; the two open children below (scripts personal-info, git-history scrub) remain. *** 2026-07-09 Thu @ 16:32:54 -0500 Audit reconcile: docs/ scrubbed; scripts and history still open The =docs/= half of "remove personal information" landed (=a8f7e9b=). Four absolute =/home/cjennings= paths became the repo root, a home-relative path, or a named variable — every snippet stays runnable. Three =~/projects/home= references and three =.ai/sessions/= links, all dead in any clone but Craig's, were replaced by what they mean. No =file:= links broke. @@ -1383,6 +1447,8 @@ Recommend: fresh repo for GitHub (keep cjennings.net remote with full history). History is now 589 commits (the 2026-05-11 note's "275" is stale). Only the calendar-feed file has been filter-repo'd so far (2026-05-20). The five credential files remain in history at their pre-=b10cba5= paths: =.tidal-dl.token.json= (5 commits), =calibre/smtp.py.json= (6), =transmission/settings.json= (5), =.msmtprc= (8), =.mbsyncrc= (9). None are tracked in the current tree. The scrub-or-fresh-repo decision still stands. ***** 2026-07-04 Sat @ 11:48:24 -0500 Count refresh — history now 565 commits; re-verify the 5-file claim before scrubbing The 2026-07-04 audit found the history is now 565 commits, down from the 589 recorded above. Because the count dropped, re-verify that the five credential files are still present in history (re-run the per-file =git log --all -- <path>= check) before relying on the scrub scope — the earlier count is stale and the file set may have moved. +***** 2026-07-21 Tue @ 08:00:00 -0500 Re-verified: history now 851 commits; five files still present, per-file counts dropped +2026-07-21 audit re-verification. History is now 851 commits (=git rev-list --all --count=). The five credential files are still in history but at fewer commits each than the 2026-06-28 record: =.tidal-dl.token.json= 3 (was 5), =calibre/smtp.py.json= 4 (was 6), =transmission/settings.json= 3 (was 5), =.msmtprc= 5 (was 8), =.mbsyncrc= 6 (was 9). None are in the current tree. The scrub-or-fresh-repo decision still stands; the scope is smaller than recorded. *** 2026-06-24 Wed @ 19:41:56 -0400 Gated device-specific udev rules behind a flag The Logitech BRIO udev rule is now wrapped in =if [ "$install_device_udev_rules" = "true" ]=, fed by a new =INSTALL_DEVICE_UDEV_RULES= key (default yes, opt-out — still mainly a personal project). Added the var default, the config read, a =validate_config= check, and an =archsetup.conf.example= entry. Verified: default/yes writes the rule, no skips it, bogus is rejected; =bash -n= clean. @@ -1455,13 +1521,27 @@ 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. -** TODO [#C] WireGuard import is now config-less — decide feature fate :feature:network: -scripts/import-wireguard-configs.sh reads assets/wireguard-config/*.conf, but no configs ship in the repo anymore (removed as a public-leak fix; .gitignore blocks plaintext). Decide: remove the import feature entirely, or keep it and document dropping plaintext configs into the dir out-of-band at install time (they stay gitignored). If kept, confirm the script no-ops gracefully when the dir has no *.conf. +** DONE [#C] WireGuard import is now config-less — decide feature fate :feature:network: +CLOSED: [2026-07-21 Tue] +Decided 2026-07-21 (Craig): KEEP the import feature. The out-of-band flow is already in place — =assets/wireguard-config/= carries a README documenting "drop plaintext =*.conf= locally at install time (gitignored); ship encrypted =*.conf.gpg= to track", and its =.gitignore= enforces it (=*.conf= blocked, =!*.conf.gpg= allowed). The script also already no-ops gracefully on an empty dir (=shopt -s nullglob= + a =found= flag), so nothing ships and nothing errors when no configs are present. Nothing to build; the fate decision was the whole task. +scripts/import-wireguard-configs.sh reads assets/wireguard-config/*.conf, but no configs ship in the repo anymore (removed as a public-leak fix; .gitignore blocks plaintext). ** TODO [#C] Waybar modules run together — need subtle separators :bug:dotfiles:waybar: 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] Dupre theme waybar.css drifted from live style.css :bug:dotfiles:waybar: +** TODO [#C] Weather chip color signals unclear + unenforced :bug:dotfiles:waybar:weather: +:PROPERTIES: +:LAST_REVIEWED: 2026-07-21 +:END: +From the roam inbox (2026-07-20): the shipped Waybar weather chip's comfort coloring reads as noise — it shows amber for no clear reason, and some items are bolded, which isn't a legible signal. Craig's intended scheme (every item except the arrow key colored by whether the weather is comfortable; NO bold or italic anywhere): +- Normal — all text white: temp in 60-85; condition sunny/clear/etc. +- Poor conditions — colored glyph: rain = blue glyph; snow = bright-blue glyph; fog = silver glyph. +- Bad conditions — red number: temp over 90 → the temp number is red; wind over a comfort level → the wind glyph displays and its number is red. +Open design question (Craig): which other conditions/combinations to signal, and how a forecasted severe event (e.g. an upcoming hurricane) should display. +Grading: Minor severity (legibility on a shipped chip, nothing broken) × frequent (every glance at the bar) = P3 = [#C]. Mostly buildable from the rules above; the severe-event display needs Craig's call. Waybar is archsetup-owned per the dotfiles standing rule. +** DONE [#C] Dupre theme waybar.css drifted from live style.css :bug:dotfiles:waybar: +CLOSED: [2026-07-21 Tue] +Fixed in dotfiles 3e4e7ff (2026-07-20, "fix(theme): sync dupre waybar.css with the live weather rules") — dupre/waybar.css is byte-identical to live again, restoring the =#custom-weather= selectors/hover/gold divider, so =tests/theme-css= is green. Grading: Minor severity (cosmetic, reverts only on a theme switch) × rare edge case (dupre is already the active theme) = P4 = [#D] on user impact, bumped to [#C] because the dotfiles =make test= stays RED until synced, poisoning the green baseline for every future commit. The weather-kit work added =#custom-weather= selectors to =hyprland/.config/waybar/style.css= but never mirrored them into =hyprland/.config/themes/dupre/waybar.css=. =tests/theme-css= asserts the two files are identical (set-theme copies the theme file over the live one), so switching to dupre would silently revert the weather chip styling. Fix: sync the theme file to live. Pre-existing; found 2026-07-19 during an unrelated commit's green-baseline run. @@ -1494,13 +1574,15 @@ Suspected cause: the check clicks the 3x size chip, calls =scrollIntoView=, wait Why it matters beyond the annoyance: a gate that cries wolf gets its real failures ignored, and this suite is the only thing standing between the gallery and a silent regression. -Recurrences: 2026-07-18 batch-6 gate (first run, passed 3 reruns); 2026-07-18 batch-9 gate (first cold run, =level 68 -> level 68=, passed 2 reruns). Both were the session's first probe run — consistent with the stale-rect theory (cold-start relayout settling slower than the fixed 200ms sleep). +Recurrences: 2026-07-18 batch-6 gate (first run, passed 3 reruns); 2026-07-18 batch-9 gate (first cold run, =level 68 -> level 68=, passed 2 reruns); 2026-07-21 double-speedrun run (flashed one RED mid-run, passed on rerun). All were a session's first/early probe run — consistent with the stale-rect theory (cold-start relayout settling slower than the fixed 200ms sleep). ** TODO [#C] Maint live-refresh hairline replacement :feature:maint: :PROPERTIES: :LAST_REVIEWED: 2026-07-14 :END: From the roam inbox (routed 2026-07-13): the memory-killer section seemed to update too often, and "it's a bit unclear what the line is doing; consider something else." Diagnosis (2026-07-14): the data cadence is already the requested 3s (gui live tier, _LIVE_SECONDS); the perceived churn is the live-refresh hairline — the 2px bar under the live sections that drains full-to-empty over each 3s window, redrawn at 150ms (gui._hair_tick, viewmodel.refresh_fraction). It exists to tell a stale board from a frozen one (2026-07-09), but it reads as constant unexplained motion. Design call for Craig: replace the draining line with something whose meaning is legible — candidates: a dot that blinks once per refresh, a "3s" age caption that only appears when refresh is overdue, slowing the drain redraw, or dropping the indicator on live tiers and keeping it only when data goes stale. Keep the stale-vs-frozen distinguishability that motivated the hairline. +*** 2026-07-21 Tue @ 08:35:00 -0500 Decided (Craig): silent-until-stale age caption +Replace the draining 2px hairline with an age caption that shows ONLY when refresh is overdue (e.g. "3s", "8s" once past the expected window) and shows nothing while the board is healthy. This keeps the stale-vs-frozen signal — a frozen board surfaces a growing age number, a live one stays clean — while removing the constant motion the hairline created. Implementation (dotfiles, archsetup-owned): drop =gui._hair_tick= / the hairline draw, add an overdue-age caption driven off =viewmodel.refresh_fraction= (or the last-refresh timestamp) rendered only past the live window. Now unblocked; needs a live visual check on the panel after. ** TODO [#C] Net panel speedtest history :feature:dotfiles:network: :PROPERTIES: @@ -1526,9 +1608,10 @@ Ratio's ~/.config/calibre is a directory symlink into the dotfiles repo (stow fo The solo-able subset landed in the speedrun. =make conflicts <de>= is the loud first-launch guard: dry-runs all tiers, parses all four stow error shapes (plain file conflict, foreign symlink, dir-over-file, and restow's unstow_contents non-directory ERROR), lists each blocker with a directory/foreign-symlink marker, exits 1 when any exist. =make reset= now pre-clears the directory and foreign-symlink blockers =--adopt= aborts atomically on (removals printed; repo version wins per the target's contract), then adopts + git-checkouts as before. =make restow='s overwrite path switched rm -f → rm -rf so directory conflicts clear. 8 sandbox tests drive the real Makefile against a throwaway HOME (44 suites green). Also verified on velox: the whereami and mpd-playlists conflicts noted in this task were already hand-converted 2026-06-29 — =make conflicts hyprland= reports clean live. REMAINING (deferred per Craig's speedrun pre-flight): the waypaper canonical decision (live velox dark-lion.jpg vs repo that-one-up-there.jpg) and the ratio calibre-symlink check (ratio paused). From the velox calibre incident (2026-06-27, note in ~/.dotfiles/inbox/processed/): calibre was launched before =make stow= ran, wrote its own default config into =~/.config/calibre/=, and silently blocked its own stow — it ran on factory defaults while the rest of common/ stowed fine. General pattern: any GUI app that auto-creates config on first run, launched before stow, blocks its own stow the same way. Velox was repaired by hand (=ln -srf= symlinks byte-identical to =stow --no-folding= output). -Remaining work (re-graded C 2026-07-02 — the first-launch risk and the Makefile handling shipped in the speedrun; what's left is a decision and a paused-machine check): -- Waypaper canonical decision (Craig): live velox has =dark-lion.jpg=, repo has =that-one-up-there.jpg= (placeholder?). Decide the canonical, then =make reset= clears it. -- Ratio check: whether =~/.config/calibre/*.json= on ratio are symlinks or real files — same first-launch gap likely if calibre ever launched there before stow. On the ratio trip list. +Remaining work (re-graded C 2026-07-02 — the first-launch risk and the Makefile handling shipped in the speedrun; what's left is a paused-machine check): +- Waypaper canonical decision (Craig): RESOLVED 2026-07-14 — dark-lion.jpg is canonical (dotfiles fea3e93), repo config.ini updated off the that-one-up-there.jpg placeholder. +- Ratio check: RESOLVED 2026-07-14 — ratio's =~/.config/calibre= is a directory symlink into the repo (stow folded the dir), so the first-launch gap never existed there. +- When velox is back online: run =make conflicts= / =make reset= there so its old conflict copy clears against the updated repo. (velox carries a separate boot-recovery task; check once it's reachable.) ** TODO [#C] Waybar collapse control: replace the triangle glyph :feature:waybar: :PROPERTIES: @@ -1549,6 +1632,8 @@ Follow-up from the 2026-07-04 net-panel hardening speedrun (Craig's cj question Push-to-talk dictation that types transcribed speech into the focused Wayland window — usable at any text field, including the Claude Code terminal prompt and Emacs buffers. Claude Code has no built-in voice input; dictation has to happen at the OS level and inject text. Raised 2026-07-03. Tool choice is the open decision (needs Craig): =nerd-dictation= (Vosk, lighter, lower accuracy) vs a =whisper.cpp=-based daemon (heavier, higher accuracy, optional GPU). Wayland typing backend is =wtype= or =ydotool=. Scope once chosen: install + model download, a push-to-talk keybind (Hyprland), and an autostart entry; fold into archsetup so it lands on both daily drivers. Consider an Emacs-native path (=whisper.el=) as a complement for in-buffer dictation. +*** 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). ** TODO [#C] Fix install errors surfaced by the 2026-05-11 VM test run :PROPERTIES: @@ -1580,6 +1665,8 @@ Root cause was in =retry_install=: =last_exit_code=$?= ran AFTER =if eval ...; t ** TODO [#C] Osbot camera configuration :chore: Craig's roam capture 2026-07-20, routed via .emacs.d sentry inbox-zero as archsetup-owned device setup: "configure osbot camera." Scope to define at pickup (device model, what "configure" covers — kernel module, v4l settings, default framing). +*** 2026-07-21 Tue @ 08:10:00 -0500 Scoped (Craig): tiny — it works, just needs configuring via a panel +Craig: the camera works (bought for being Linux-friendly), it just needs configuring. There IS a config panel — =cameractrls= 0.6.10 is installed (a GTK GUI for camera controls: exposure, white balance, PTZ, focus, framing) plus =v4l-utils= for the CLI path. Caveat found 2026-07-21: no =/dev/video*= device is present right now, so the camera isn't currently plugged in / its UVC node isn't enumerated. Task: with the camera connected, confirm it enumerates as a /dev/video node, then set defaults in cameractrls. Small, mostly a live-hardware step. ** TODO [#C] Re-check python-lyricsgenius --skipinteg workaround :chore:solo: :PROPERTIES: :LAST_REVIEWED: 2026-07-09 @@ -1610,6 +1697,8 @@ error-prone — changes must be made in both places. Consider: - Or symlinking the stowed config to a theme-managed location - Same situation applies to fuzzel.ini 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. ** TODO [#C] Review current tool pain points annually :PROPERTIES: @@ -1621,6 +1710,8 @@ Once-yearly systematic inventory of known deficiencies and friction points in cu 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 In 67d0b6e: the four yes/no config-validation blocks collapse into validate_yesno (TDD), and the driver-floor literal 535 becomes NVIDIA_MIN_DRIVER. The safe, purely-testable slice; the remaining 10 (structural / system-mutation) stay parked above. +*** 2026-07-21 Tue @ 08:00:00 -0500 Audit reconcile: the GRUB cmdline sed slice shipped +f9da097 (2026-07-21) rewrote the boot-critical =GRUB_CMDLINE_LINUX_DEFAULT= sed into a guarded awk+mv merge with a backup and added characterization tests (tests/installer-steps/test_grub_cmdline.py). So the "GRUB sed clusters want characterization coverage before rewrite" caveat no longer covers the cmdline line — only the 4 cosmetic GRUB sed lines (timeout/default/terminal/gfxmode, which overwrite fixed values with nothing to preserve) remain in that slice. ** TODO [#D] Test-framework + prototype refactor cluster :refactor: Grading: no behavior change; parking lot. Refactors from the S5-S7 audit, distinct from the installer refactor rollup above. scripts/testing/run-test.sh + run-test-baremetal.sh duplicate the run/poll/report skeleton and have drifted (VM uses setsid + copy helpers, baremetal uses nohup + hand-rolled sshpass scp) — extract the shared core so baremetal inherits the sturdier paths; run-maint-nspawn.sh:66 + run-maint-scenarios.sh:78 duplicate the transport-independent _scenario_var/_validate_scenario/run_scenario (a sourced lib/maint-scenario.sh); run-test.sh:251,265 uses two different mechanisms (pgrep vs ps|grep) for the same liveness check; docs/prototypes/gen_tokens.py:78 repeats the section-iteration skeleton across four emitters; gallery-widget.el:95,136 hardcodes SVG arc/hub path strings that duplicate the cx/cy/radius geometry (dial desyncs silently on a constant change); gallery-widget.el:72,84 leans on the private svg--append. See findings doc (S5, S6, S7). @@ -1631,7 +1722,7 @@ Deferred from the [[file:docs/specs/2026-07-11-net-doctor-expansion-spec.org][ne Deferred from the [[file:docs/specs/2026-07-11-bt-doctor-expansion-spec.org][bt doctor expansion spec]] (IMPLEMENTED, v1 shipped): the stale-bond re-pair-offer signature (v1 keeps re-pair strictly user-initiated; the signature must be designed and validated before the doctor ever offers it); a connection-parameter/coexistence hint tail for a "keeps dropping" verdict; the bt-audio-profile expansion beyond the current a2dp repair (codec fallback, default-sink, absolute-volume) — wants coordination with the audio doctor so the two panels don't claim the same A2DP/HFP diagnosis with divergent verdicts. ** TODO [#D] Widget catalogue vNext :feature:design: -Deferred from the [[file:docs/specs/2026-07-12-component-generation-spec.org][component-generation spec]] (DRAFT): framework wrappers for the web library (React or otherwise — demand-gated, none until a real framework consumer exists); Level-2/3 widget codegen if the spec's Phase 5 decision point says go (a go spawns its own spec); ports beyond the demand matrix as new consumers appear. +Deferred from the [[file:docs/specs/2026-07-12-component-generation-spec.org][component-generation spec]] (DOING): framework wrappers for the web library (React or otherwise — demand-gated, none until a real framework consumer exists); Level-2/3 widget codegen if the spec's Phase 5 decision point says go (a go spawns its own spec); ports beyond the demand matrix as new consumers appear. ** TODO [#D] Maintenance console vNext :feature: Deferred from the [[file:docs/specs/2026-07-07-maintenance-console-spec.org][spec]] (v1 ships determinate remedies only): AI/workflow assistance on read-only metrics (the vLater tier — failed-unit diagnosis, journal-error fix suggestions, OOM investigation); SIGKILL escalation for TERM-survivors on the KILL lever; live streaming meters on evidence rows where a count could be a level. @@ -1670,11 +1761,18 @@ Parse yay errors and provide specific, actionable fixes instead of generic error ** TODO [#D] Improve progress indicators throughout install Enhance existing indicators to show what's happening in real-time -** TODO [#D] Telega coredump recurrence tell :bug:maint: +** TODO [#C] Telega coredump recurrence tell :bug:maint: :PROPERTIES: -:LAST_REVIEWED: 2026-07-09 +:LAST_REVIEWED: 2026-07-21 :END: +*** 2026-07-21 Tue @ 08:10:00 -0500 Re-graded D → C (Craig): treat as the actionable version-skew recurrence +Craig's call: the fired tell counts as the version-skew recurrence this task predicts (zevlg =:latest= outran the installed elisp again), not just benign host noise — so it bumps [#D] → [#C]. Action: re-pin / upgrade the TDLib side (upgrade the elisp telega package on ratio+velox, or move to a host-native pinned TDLib build) so the server's plist parser and the installed elisp agree again. The durable escape remains the host-native pinned TDLib build. + +*** 2026-07-21 Tue @ 08:00:00 -0500 Audit reconcile: the tell FIRED — coredumps recurred +The named tell has tripped. =~/.telega/telega-server.log:11413= now carries a fresh =Assertion failed: false (telega-dat.c: tdat_plist_value: 500)=, and =coredumpctl= shows telega-server SIGSEGV recurring on ratio: a burst of 8 on 2026-07-15, then 07-16, 07-18, 07-19, newest 2026-07-20 23:41. The 2026-07-09 "nothing recurred" verdict below is superseded. +Open question for Craig (re-grade): is this the version-skew recurrence this task predicts (zevlg =:latest= outran the installed elisp again — actionable: re-pin/upgrade TDLib) or the separately-known benign dockerized-musl SIGSEGV class (the health-check known-issues entry, cosmetic host-coredump noise)? The answer decides whether this bumps back [#D] → [#C]. Note the health-check on 2026-07-21 classified this boot's telega coredumps as KNOWN musl-build noise, which argues against a version-skew regression — but the fresh tdat_plist_value assertion is the skew signature, so the two need reconciling. + *** 2026-07-09 Thu @ 16:32:54 -0500 Audit reconcile: the fix is holding; re-graded C → D Verified rather than assumed: =~/.telega/telega-server.log= carries zero =tdat_plist_value= assertions, and the newest telega-server coredump is 2026-07-08 16:57 — before .emacs.d upgraded the elisp. Nothing has recurred. |
