diff options
| author | Craig Jennings <c@cjennings.net> | 2026-08-17 11:30:06 -0700 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-08-17 11:30:06 -0700 |
| commit | 5c7a5888ed2a68476500b00d4fe3df5d3bde2f0f (patch) | |
| tree | 2b66683f9fafd30e69c6ce705707b6798977d2f0 | |
| parent | 4dfecc5f705c9df0d1f8e8245276146f826e16cc (diff) | |
| download | archsetup-5c7a5888ed2a68476500b00d4fe3df5d3bde2f0f.tar.gz archsetup-5c7a5888ed2a68476500b00d4fe3df5d3bde2f0f.zip | |
chore(todo): file what today's work turned up, and fix two checks that lied
Four tasks are new. The installer clones my own archsetup and dotfiles repos with --depth 1, so both came back from the rebuild with seven commits of history instead of hundreds. Power profiles crash on a loop against the daemon this repo now masks. The user manager on that machine is spinning and cannot resolve unit files. The new post-rebuild-check wants its probes routed through one guarded helper, because four separate "the probe failed and the check said ok" bugs is a shape rather than four mistakes.
I rechecked two recurring items against their own unblock conditions rather than re-stamping them. The zfs DKMS build is still waiting on an upstream release, and the lyricsgenius integrity workaround still fails for the same structural reason.
The credential-history entry has been asking a question git could not answer. The filenames recorded there are not the paths those files live at, and a path git has never seen returns no commits rather than an error, so every check since June came back falsely clean. I corrected them to the real paths, which turn out to be six files rather than five.
| -rw-r--r-- | todo.org | 277 |
1 files changed, 241 insertions, 36 deletions
@@ -120,6 +120,192 @@ hand-copied key sprawl; a firm RAM carve-out so builds don't fight the ZFS ARC; headless only — desktop-coupled sessions stay on ratio/velox. Build deliberately AFTER the vacation, not before Sunday. Companion idea (cheaper, complementary): put ratio on the UPS. +** TODO [#B] post-rebuild-check: route every probe through one guarded helper :refactor:solo: +:PROPERTIES: +:CREATED: [2026-08-17 Mon] +:LAST_REVIEWED: 2026-08-17 +:END: +The script works and is well tested, but its shape keeps producing the same +bug. Across three review rounds the reviewer found FOUR separate instances of +"the probe failed and the check reported ok", each in a different place: +=systemctl= in check 1, the enablement read in check 2, =find= in check 3, and +=grep= in check 4. A fifth was latent in an unguarded staged write. Every one +was individually fixed, and I only stopped finding more because someone kept +looking. + +That is a design problem rather than four bugs. The script has five +hand-written probes, and each one has to remember to branch on its own exit +status. Nothing enforces it, nothing fails a review that forgets it, and the +failure is invisible because the wrong behaviour is a clean "ok". + +Shape: one helper every probe must go through, which cannot return a value +without an explicit success, so that "I could not read this" is +unrepresentable as "nothing to report". Roughly: + +: probe "<what>" <command...> # sets a value on success, records a finding otherwise + +Then each check consumes the helper's result rather than a raw command +substitution, and a new check written later inherits the discipline instead of +having to re-derive it. Worth pairing with a test that asserts no check can +report ok when its probe exits non-zero, generically, so the fifth instance is +caught by the suite rather than by a reviewer. + +Not urgent: the current version is correct as far as anyone has found, ships +with 58 tests, and proved itself on a genuinely wedged machine. This is +prevention. + +Grading: Minor severity (no known live defect, the risk is future) x +most-users-frequently (every future edit to this script) = P3 = [#C]... except +the failure mode is silent and the script's whole job is catching silent +failures, so a regression here is uniquely undetectable. P2 = [#B]. + +:solo: — the surface is one script and its suite, the refactor is +behaviour-preserving, and the existing 58 tests plus a mutation battery are +the objective check that it stayed so. +** TODO [#A] powerprofilesctl crashes on a loop since ppd was masked :bug:velox:dotfiles: +:PROPERTIES: +:CREATED: [2026-08-17 Mon] +:LAST_REVIEWED: 2026-08-17 +:END: +Something polls power state every 10-30 seconds, and each poll runs +=powerprofilesctl get=, which SIGABRTs. 47 coredumps on velox on 2026-08-17 +alone, the earliest at 08:34, four in one minute while I was watching. + +Cause is the 2026-08-16 fix that masked =power-profiles-daemon= so TLP +survives on laptops. That fix is right and stays. What it did not account for +is the settings module's power backing +(=~/.dotfiles/settings/src/settings/power.py=), which shells out to +=powerprofilesctl=. Against a masked unit the D-Bus activation fails with +=NameHasNoOwner ... unit is masked=, and the caller aborts rather than +degrading. + +Run by hand the same command exits 0 and prints the error, so the abort is +context-dependent and the caller needs finding before the fix is written. +Ratio does not mask ppd, which is why this is velox-only and why it appeared +the day after the masking. + +Costs: journal spam, coredump disk churn, and repeated failed D-Bus +activations on a travelling laptop's battery. It is also the leading suspect +for the wedged user manager filed below. + +Fix shape: =power.py= should treat a masked or unavailable ppd as a +first-class "no profile control here" state rather than an error path, and +the poller should stop retrying a unit it has been told is masked. The +machine-level half is already correct. + +Grading: Major severity (a crash loop burning battery and filling the +journal, silently) x every user every time on any laptop with the TLP fix +applied = P1 = [#A]. +** TODO [#A] velox's systemd --user spins at 96% and cannot resolve unit files :bug:velox: +:PROPERTIES: +:CREATED: [2026-08-17 Mon] +:LAST_REVIEWED: 2026-08-17 +:END: +Live on velox 2026-08-17 from about 10:29. =systemd --user= (pid 2235) sits +in state R at 96% CPU, measured over a 3-second sample rather than taken from +the lifetime average. It stopped logging at 10:29, so its timers appear to +have stopped firing too. + +The split is the diagnostic: =systemctl --user list-units= still returns +instantly, while =is-enabled=, =cat=, =show=, and =list-unit-files= all hang +indefinitely. So the manager answers from its in-memory unit list and wedges +on anything that has to resolve unit files. It is spinning in userspace, not +blocked on I/O (=/proc/2235/wchan= is 0, no syscall pending). + +Remedies tried, neither worked: =systemctl --user daemon-reexec= hangs like +every other unit-file call, and the signal form (=kill -59=, SIGRTMIN+25) +was accepted but changed nothing. The next step is a logout/login or reboot, +which is Craig's call because it closes his running session. I deliberately +did not kill the manager: that would tear down the graphical session and +everything under it. + +Suspected cause is the powerprofilesctl crash loop filed above, whose +repeated activation attempts against a masked unit are the only new load on +this machine. I cannot prove it, and I have to name the other candidate +honestly: my own =post-rebuild-check= runs called =systemctl --user +is-enabled= roughly thirty times per run over several runs, and the wedge +appeared during that window. The crash loop predates those runs by an hour +and a half, which is why it is the leading suspect rather than the certain +one. + +What it costs: unit-file operations are unavailable, user timers appear +stopped, and a core is pinned on a laptop running on battery. + +Grading: Major severity (a pinned core and stopped user timers, invisible +unless you look) x rare edge case (one machine, specific conditions) = P2 = +[#B]... except that this is a live, ongoing drain on a travelling machine +rather than a latent defect, so it takes [#A] until the machine is back to +normal. Re-grade to [#B] once resolved and the question is only prevention. +** TODO [#A] The installer shallow-clones the two repos I develop in :bug:velox:solo: +:PROPERTIES: +:CREATED: [2026-08-17 Mon] +:LAST_REVIEWED: 2026-08-17 +:END: +=archsetup:1432= clones the user's archsetup repo and =archsetup:1445= clones +dotfiles, both with =--depth 1=. Those are not build directories. They are the +two repos I actively develop in, and on velox they came back from the +2026-08-13 rebuild with 7 commits of history each instead of 851. + +Found 2026-08-17, and found the worst way: I ran the credential-file history +check that the GitHub-release task asks for, and it reported all five files +absent from history with a clean exit. The real answer is that this clone +cannot see the history those files live in. A shallow clone does not error on +=git log -- <path>=, it answers "no commits" — so a security question came back +falsely clean, and nothing about the output said otherwise. + +Everything else it breaks is quieter: =git log=, =blame=, =bisect=, and any +archaeology past the boundary. The tree looks completely normal, which is why +this survived four days on the machine. + +The right shape is already in the codebase. =scripts/post-install.sh:42-51= +takes depth as a per-repo argument and defaults to a full clone, so wallpaper +gets =--depth 1= and org does not. The AUR build clones (=archsetup:855=, +=:1673=, =:1677=) are correctly shallow and stay that way. Only the two +user-repo sites change. + +Repair on a machine already built: =git fetch --unshallow= in each repo. + +Grading: Major severity (two working repos silently missing their history on +the machine I develop on, and it returns confidently wrong answers to history +questions rather than failing) x every user every time (every fresh install, +both daily drivers) = P1 = [#A]. + +:solo: — the change is two lines plus tests in the existing +=tests/installer-steps/= shape, and it is verifiable locally by asserting the +clone command carries no =--depth= for these two repos. +** TODO [#B] post-rebuild-check needs a reference-host mode :feature:velox:solo: +:PROPERTIES: +:CREATED: [2026-08-17 Mon] +:LAST_REVIEWED: 2026-08-17 +:END: +=scripts/post-rebuild-check= ships and works, but its first live run on velox +2026-08-17 showed the output is mostly steady state rather than drift. Of the +8 findings that survived three rounds of false-positive removal, comparing +against ratio says exactly ONE is real: =obsbot-wb-guard= is enabled on ratio +and merely linked on velox, which is the deliberate deferral recorded +2026-08-16. The other three unit findings (=emacs=, =geoclue-agent=, +=obs-record-watchdog.timer=) are linked on ratio too, and the three =.claude= +absences are absent on ratio too. + +So the signal-to-noise is about 1:7, and the thing that separates them is a +comparison against the other daily driver — the same discipline that kept the +2026-08-16 session honest when check 4 read as nine projects missing +=CLAUDE.md= and ratio turned out to be missing the identical files. + +Shape: =--reference-host <host>= runs the same five checks on the far machine +over tailscale (ssh, read-only) and reports only the *differences*. Findings +present on both machines are steady state and get summarized as a count rather +than listed. Falls back to the current standalone behavior when the reference +host is unreachable, and says so. + +Grading: Minor severity (the tool works and its findings are accurate; they +are just buried) x every use = P3 = [#C]... except that a check nobody reads +is a check that isn't run, which is the failure mode the whole task existed to +close. Most-users-frequently x Major = P2 = [#B]. + +:solo: — the checks exist, the ssh path is proven (the 2026-08-17 session ran +exactly this comparison by hand), and correctness is verifiable locally by +diffing the two reports. ** TODO [#C] screen-lock test suite red on ratio :bug:test:dotfiles: :PROPERTIES: :CREATED: [2026-08-13 Thu] @@ -291,6 +477,7 @@ dial placement 2026-08-13): Note: ratio has no swap partition, so hibernate stays velox-only until ratio gets one; the dial entry should degrade gracefully where there's no resume target. +** TODO [#A] Move secrets out of public dotfiles → private repo + combined personal ISO :feature:security:dotfiles: :PROPERTIES: :CREATED: [2026-08-11 Tue] :LAST_REVIEWED: 2026-08-11 @@ -310,6 +497,40 @@ archangel+archsetup ISO that's already ~80% built. Two ISO modes: generic don't start the migration until the credentials are rotated. Not started. Not :solo: — repo standup and history rewrite are Craig's calls; promote to a real spec (spec-create) when work resumes. +** TODO [#B] Settings toggles reset silently at session start :bug:dotfiles: +: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. ** VERIFY [#A] Pre-vacation fix list — morning review SCHEDULED: <2026-08-08 Sat> :PROPERTIES: @@ -1961,7 +2182,7 @@ NOTE (2026-07-04 audit): the "four-tab panel" framing predates the instrument-co ** DOING [#B] Prepare for GitHub open-source release :PROPERTIES: -:LAST_REVIEWED: 2026-07-09 +:LAST_REVIEWED: 2026-08-17 :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 @@ -2018,6 +2239,19 @@ 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-08-17 Mon @ 10:20:00 -0700 Corrected the paths — every prior check has been querying paths that never existed +The five filenames recorded above are not the paths these files live at, and =git log -- <path>= answers "no commits" for a path it has never seen rather than erroring. So the checks return a clean result and mean nothing. The real paths, from =git log --all --name-only --diff-filter=A= over the full history, all sit under the pre-migration =dotfiles/= tree: + +- =dotfiles/system/.msmtprc= (3 commits) +- =dotfiles/system/.mbsyncrc= (2) +- =dotfiles/system/.config/calibre/smtp.py.json= (2) +- =dotfiles/system/.config/transmission/settings.json= (2) +- =dotfiles/system/.config/.tidal-dl.token.json= (2) +- =dotfiles/system/.config/.tidal-dl.json= (2) — a *sixth* file, never recorded here + +Use those paths for any future check, not the bare filenames. History is 891 commits; none of the six are in the current tree. The scrub-or-fresh-repo decision still stands and its scope is six files, not five. + +This surfaced while re-verifying on velox, where the check ALSO returned a false clean for a second, unrelated reason: the clone was shallow (7 commits), so it could not see the history either way. Both failures produce the same confident zero. Filed as =[#A] The installer shallow-clones the two repos I develop in=. ***** 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. @@ -2149,9 +2383,11 @@ From the roam inbox (routed 2026-07-13): the networking panel should track speed ** TODO [#C] zfs base VM image build failure: ZFS DKMS module missing :bug:zfs: :PROPERTIES: -:LAST_REVIEWED: 2026-07-09 +:LAST_REVIEWED: 2026-08-17 :END: =FS_PROFILE=zfs make test-vm-base= fails inside the VM at initramfs time: archangel reports "ZFS module not found! DKMS build may have failed" against the installed kernel (linux-lts 6.18.38 at the 2026-07-08 attempt). Consequences: the maint scenario harness's zfs lane (Phase 12) is filtered but unexercised, and a real zfs bare-metal install via archangel would plausibly hit the same wall. Priority per the bug matrix: Major severity (zfs install path broken) × some-users-sometimes = P3. When fixed, run =FS_PROFILE=zfs bash scripts/testing/run-maint-scenarios.sh --list= and add zfs scenario files (zpool scrub / autotrim / snapshot destroy) to the harness. +*** 2026-08-17 Mon @ 10:08:51 -0700 Rechecked: archzfs still on 2.3.3, still blocked +Ran the unblock check from the diagnosis below: archzfs' x86_64 index still serves only =zfs-dkms-2.3.3=. The first release supporting 6.18 is 2.4.0, so the blocking condition is unchanged and there is still nothing on our side to fix. Recheck again with the same one-liner. *** 2026-07-14 Tue @ 01:40:48 -0500 Diagnosed: OpenZFS/kernel version skew, blocked on archzfs Reproduced in ~1 minute of install: =dkms install zfs/2.3.3 -k 6.18.38-2-lts= exits 1 during pacstrap. Root cause confirmed: OpenZFS 2.3.3's META declares Linux-Maximum 6.15, and the VM installs linux-lts 6.18.38. The first release supporting 6.18 is 2.4.0 (2.4.1 covers 6.19), and archzfs currently serves only zfs-dkms 2.3.3-1 — nothing on our side to fix. Unblock condition: archzfs publishes zfs-dkms ≥2.4.0; recheck with =curl -s https://archzfs.com/archzfs/x86_64/ | grep -o 'zfs-dkms-[0-9.]*'=, then rerun =FS_PROFILE=zfs make test-vm-base=. @@ -2191,10 +2427,12 @@ Craig's roam capture 2026-07-20, routed via .emacs.d sentry inbox-zero as archse 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 +:LAST_REVIEWED: 2026-08-17 :END: archsetup installs =python-lyricsgenius= with =--mflags --skipinteg=, skipping makepkg integrity + PGP checks — a workaround originally for an expired-signature issue upstream (surfaced by the 2026-06-23 --noconfirm audit). Periodically test whether the cause has cleared: if a plain =aur_install python-lyricsgenius= builds without complaint, drop the =--skipinteg= workaround. Removal needs a real AUR build to confirm, so it isn't a blind change. +*** 2026-08-17 Mon @ 10:08:51 -0700 Rechecked: still needed, cause unchanged +Fresh AUR clone, =makepkg --verifysource= on 3.7.0-1: the PyPI tarball passes, =LICENSE.txt= still FAILS its b2sum. The PKGBUILD still pins the license at github master, so its checksum drifts whenever upstream touches the file. =--skipinteg= stays. *** 2026-07-23 Thu @ 02:20:00 -0500 Rechecked: still needed, unchanged Fresh AUR clone, =makepkg --verifysource= on 3.7.0-1 (PKGBUILD still unchanged since the last check): the PyPI tarball passes, =LICENSE.txt= still FAILS its b2sum. Same structural cause — the source pins the license at github master, so its checksum drifts whenever upstream touches the file. =--skipinteg= stays. Nothing to change in the installer. @@ -3506,39 +3744,6 @@ ratio and absent on velox; full evidence and rationale in 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: |
