From 5fe4b7d28ab78c46b9ca850e6f7ef0bca14702c3 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Wed, 29 Jul 2026 06:27:35 -0500 Subject: chore(todo): archive resolved work and move the wolf config out of the tree Three finished subtrees move into Resolved: the runpm reboot, the caffeine readability fixes, and the relaunch-logging task that its own instrument superseded. The encrypted wolf config now lives outside this repo. Leaving it untracked in the working tree was the wrong resting place, because one "git add -A" would put a live key into a repo that cgit still serves anonymously. The importer cannot read an encrypted config anyway, so keeping it here bought nothing. --- todo.org | 131 +++++++++++++++++++++++++++++++-------------------------------- 1 file changed, 64 insertions(+), 67 deletions(-) diff --git a/todo.org b/todo.org index 25cd5a9..eb42f89 100644 --- a/todo.org +++ b/todo.org @@ -45,44 +45,6 @@ below): input-side-spec.org (DRAFT, four decisions open). * Archsetup Open Work -** DONE [#A] Reboot ratio to activate amdgpu.runpm=0 :bug:hyprland:ratio: -CLOSED: [2026-07-28 Tue] DEADLINE: <2026-07-28 Tue> -:PROPERTIES: -:CREATED: [2026-07-28 Tue] -:LAST_REVIEWED: 2026-07-28 -:END: -Craig's plan: close everything down, run topgrade, then reboot. Alarm set for 08:00 (=at= job 56, persistent desktop notify). - -=amdgpu.runpm=0= sits in =/etc/default/grub= and in the generated =/boot/grub/grub.cfg= (5 occurrences, so the reboot will actually apply it) but is absent from =/proc/cmdline=. The box has been up since 2026-07-22 21:10 and the fix landed 2026-07-24, so the running kernel predates it. The GPU is AMD Strix Halo (Radeon 8060S, =1002:1586=), exactly what the parameter targets: runtime power management invalidates the GPU resources hyprlock holds across a display power-cycle, so hyprlock exits without unlocking. - -That is the root cause under the 2026-07-27 lockdead screen. The screen-lock flock fix (dotfiles =ec18fd7=) stops one dead client from becoming a lockdead screen, but it treats the symptom -- this reboot treats the cause. - -Not :solo: — Craig closes his own session and runs topgrade first. - -Rebooted 2026-07-28 08:59. =amdgpu.runpm=0= confirmed present in =/proc/cmdline= afterward, so the parameter is finally live. - -Correction, 2026-07-29: the claim above and in the body that this is "the root cause under the 2026-07-27 lockdead screen" is wrong, and superseded. hyprlock was never crashing. Every logged exit is =rc=143=, SIGTERM, from =settings-watch= killing it by design. See =[#B] Night watch and the lock watchdog fight each other=. The reboot was still worth doing (the parameter is a genuine mitigation for a real AMD defect) but it did not fix this, and the lockdead screens continued after it. - -** DONE [#B] Caffeine state is unreadable on both surfaces :bug:dotfiles:design:solo: -CLOSED: [2026-07-28 Tue] -:PROPERTIES: -:CREATED: [2026-07-28 Tue] -:LAST_REVIEWED: 2026-07-28 -:END: -Neither surface that reports caffeine tells the truth reliably, so there is no way to know at a glance whether the screen will lock. Found while investigating the 2026-07-27 lockout, where Craig believed caffeine was on and the screen locked anyway. - -Defect 1 — the settings panel shows a frozen value. =gui.py= calls =_refresh_async()= once during window construction (line 454) and again only after the user's own actions (=_after_matrix=, line 663). The only two =GLib.timeout_add= calls are one-shots (the 2400ms toast hide and a 350ms fire), so nothing re-reads state on a timer. An open panel therefore displays the caffeine value from the moment it opened, forever. Any external flip -- the waybar click, Super+I, the =caffeine-toggle= script -- leaves it stale with no self-correction. The panel is the only surface in the repo carrying a caffeine control (=panel.py:25=); maint has none and does not embed these toggles, so this is the display Craig read. - -Defect 2 — there is no caffeine indicator on the bar at all. =custom/caffeine= appears in neither the stowed =hyprland/.config/waybar/config= nor the live generated =/run/user/1000/waybar/config=, and no =custom/caffeine= block is defined anywhere in the waybar config dir. The =waybar-caffeine= script exists, works, and has its own passing test suite, but nothing displays it. So the bar has never been a source of caffeine state, and the keybind and script have been signalling (=pkill -RTMIN+8 waybar=) a module that isn't there. - -(An earlier read of this task said the bar showed two near-identical glyphs. That was wrong: the module is absent, not merely unstyled. The script's class names are still backwards -- =active= when caffeine is OFF, =inhibited= when ON -- and neither class is styled, but both points are moot until the module is actually in the bar.) - -Grading: Major severity (the panel reports state wrongly while it is open, and the only other surface does not exist, so there is no reliable source for a setting Craig actively manages) x most-of-the-time (any external toggle while the panel is open; the bar never shows it) = P2 = [#B]. - -Fix all three. Wire =custom/caffeine= into the bar, rename its classes so they describe caffeine rather than idle, and style them from the existing palette. Give the panel's toggle row a re-read on a timer or on focus-in. Solo -- buildable and testable, and the direction is settled by the defects rather than a taste call, though the bar color is worth a glance from Craig once it renders. - -All three shipped as dotfiles =033076c=, pushed. =custom/caffeine= now sits in the bar between DND and settings on =interval: 2=; classes renamed =on=/=off= and both styled, caffeine-ON in the theme's gold =#dab53d=; the panel re-reads live state every 3s while visible. Verified live in the stowed config and the generated =/run/user/1000/waybar/config=. The full suite caught a theme-copy regression (=themes/dupre/waybar.css= out of sync with =waybar/style.css=) that the focused suites missed. - ** TODO [#B] Desktop settings don't survive a session restart :bug:dotfiles:hyprland: :PROPERTIES: :CREATED: [2026-07-28 Tue] @@ -216,34 +178,6 @@ Option 2 is the one I would argue for, but it is Craig's call. Previous title and framing of this task, kept for the record: "hyprlock still exits mid-lock; the watchdog relaunch is silent". The instrumentation that closed that gap is dotfiles =5bbe2c3=, and it paid for itself in about six hours. -** DONE [#B] hyprlock still exits mid-lock; the watchdog relaunch is silent :bug:hyprland:dotfiles: -CLOSED: [2026-07-29 Wed] -:PROPERTIES: -:CREATED: [2026-07-28 Tue] -:LAST_REVIEWED: 2026-07-28 -:END: -Craig, 2026-07-28 ~15:00: saw the Hyprland lockdead/error text blurred *behind* a working lock screen; it vanished when he authenticated. - -That ordering is the diagnosis. hyprlock's blur samples what the compositor is currently rendering, so the compositor was already showing lockdead when the new hyprlock attached. Sequence: hyprlock exits non-zero (no coredump, so it exits rather than crashing), Hyprland renders lockdead because the client is gone while the session stays locked, =screen-lock='s watchdog relaunches within =LOCK_RELAUNCH_DELAY= (0.5s), and the new client draws over the lockdead frame and blurs it. - -*The recovery worked.* On 2026-07-27 this same hyprlock exit produced two contending clients and a session recoverable only from another console. It now self-heals in half a second, and the residue is cosmetic. Both the flock guard (dotfiles =ec18fd7=) and the watchdog did their jobs — verified in this session's compositor log, where all four lock events created exactly one =sessionLock= and one =sessionLockSurface= each, against two of each on 2026-07-27. - -Two things remain. - -*Why hyprlock exits.* The wrapper's header blames GPU-resource invalidation across a display power-cycle (hyprlock#953), which =amdgpu.runpm=0= targets — and that parameter is live as of the 2026-07-28 08:59 reboot, confirmed in =/proc/cmdline=. There is also no DPMS idle rule any more (=e900903=), so idling never power-cycles the display. Yet hyprlock still exited. Strongest untested candidate: a screen recording (=wf-recorder= into =~/sync/recordings/2026-07-28-12-53-57.mkv=, running 12:53 until Craig killed it) held screencopy sessions on DP-4 across the lock. The compositor log carries 2454 screenshare sessions and a =CScreencopyProtocol= bind in the window between the last two locks. A screencopy client churning dmabufs alongside hyprlock's own is a plausible way to invalidate them, and it was the one large new variable that day. - -*The relaunch is silent.* The watchdog loop re-runs hyprlock and logs nothing, so there is no record of how often this fires, when, or with what exit code — which is exactly why the frequency couldn't be established from the logs. Log the exit code and a timestamp on each relaunch. - -Grading: Major severity (the lock client dies mid-lock, and the pre-fix version of this wedged a session unrecoverably) x most users frequently (twice in three days, and this is a single-user machine, so every occurrence lands on the only user) = P2 = [#B]. Downgraded from the 2026-07-27 [#A] because the wedge is fixed and the failure now self-heals. - -An earlier draft of this grading said "some users sometimes", which the matrix maps to P3 = [#C], not the [#B] written beside it. The frequency row was the wrong input rather than the letter: on a one-user machine a fault hitting twice in three days is frequent, not occasional. Corrected the input per the rule that a disputed grade is fixed at its inputs. - -Solo for the instrumentation half only: adding the relaunch logging is buildable, testable against the existing =tests/screen-lock= suite, and needs no decision. Diagnosing the exit is not solo — it needs a reproduction, and the likely trigger is Craig recording his screen. - -Next step when picked up: land the relaunch logging first so the next occurrence produces evidence, then try to reproduce by locking with =wf-recorder= running. - -Superseded 2026-07-29 by =[#A] Night watch and the lock watchdog fight each other=. The logging landed (dotfiles =5bbe2c3=) and answered it within hours: three =rc=143= entries, SIGTERM, from =settings-watch= killing hyprlock by design. Nothing was crashing, so both the AMD-iGPU and the screen-recorder hypotheses in this task are wrong. Kept closed rather than deleted because the reasoning that led here is worth the record. - ** TODO [#B] The wireguard gpg convention is inert; the installer can't read it :bug:security:network: :PROPERTIES: :CREATED: [2026-07-28 Tue] @@ -264,7 +198,7 @@ Not :solo: — the fix is a decision, not a build. Three options, and they inter 2. Drop the =!*.conf.gpg= exception and keep the directory genuinely empty of secrets, tracked or not, until archsetup is off the public host. 3. Do the cgit move first, then revisit. -Until it is resolved, do not commit any =*.conf.gpg=. The encrypted =wolf.conf.gpg= is deliberately left untracked in the working tree. +Until it is resolved, do not commit any =*.conf.gpg=. The encrypted =wolf.conf.gpg= now lives at =~/.config/wireguard/wolf.conf.gpg= (mode 600), moved out of this repo entirely on 2026-07-29. Untracked-in-tree was the wrong resting place for it: a single =git add -A= puts a secret into a world-cloneable repo, and the directory's own policy is unusable until the importer can actually read encrypted configs. The live NetworkManager profile is unaffected. Related: =[#B] Move archsetup off cgit= and =[#B] Audit cgit-published repos for secrets and privacy=. Both are still open, and both argue for keeping new secrets out of this repo until they land. @@ -3178,3 +3112,66 @@ Craig approved the shared-rules-layer solution on 2026-07-26. Use one repository-scoped publish lock for every session and worktree sharing a clone. Derive the lock name from the real Git common-directory path; hold it across reconcile, stage, staged review, and commit; track the owning session and reviewed staged-tree fingerprint; refresh it after conversational waits; and repeat the staged review if ownership or the fingerprint changed. Ordinary working-tree edits remain concurrent. An approval waiver never waives the staged review, because that review is the gate that reads the actual hunks entering the commit. Rulesets owns the implementation in =commits.md=, =agent-lock=, and its Bats coverage; archsetup sent the approved implementation package through the rulesets inbox. +** DONE [#A] Reboot ratio to activate amdgpu.runpm=0 :bug:hyprland:ratio: +CLOSED: [2026-07-28 Tue] DEADLINE: <2026-07-28 Tue> +:PROPERTIES: +:CREATED: [2026-07-28 Tue] +:LAST_REVIEWED: 2026-07-28 +:END: +Craig's plan: close everything down, run topgrade, then reboot. Alarm set for 08:00 (=at= job 56, persistent desktop notify). + +=amdgpu.runpm=0= sits in =/etc/default/grub= and in the generated =/boot/grub/grub.cfg= (5 occurrences, so the reboot will actually apply it) but is absent from =/proc/cmdline=. The box has been up since 2026-07-22 21:10 and the fix landed 2026-07-24, so the running kernel predates it. The GPU is AMD Strix Halo (Radeon 8060S, =1002:1586=), exactly what the parameter targets: runtime power management invalidates the GPU resources hyprlock holds across a display power-cycle, so hyprlock exits without unlocking. + +That is the root cause under the 2026-07-27 lockdead screen. The screen-lock flock fix (dotfiles =ec18fd7=) stops one dead client from becoming a lockdead screen, but it treats the symptom -- this reboot treats the cause. + +Not :solo: — Craig closes his own session and runs topgrade first. + +Rebooted 2026-07-28 08:59. =amdgpu.runpm=0= confirmed present in =/proc/cmdline= afterward, so the parameter is finally live. + +Correction, 2026-07-29: the claim above and in the body that this is "the root cause under the 2026-07-27 lockdead screen" is wrong, and superseded. hyprlock was never crashing. Every logged exit is =rc=143=, SIGTERM, from =settings-watch= killing it by design. See =[#B] Night watch and the lock watchdog fight each other=. The reboot was still worth doing (the parameter is a genuine mitigation for a real AMD defect) but it did not fix this, and the lockdead screens continued after it. +** DONE [#B] Caffeine state is unreadable on both surfaces :bug:dotfiles:design:solo: +CLOSED: [2026-07-28 Tue] +:PROPERTIES: +:CREATED: [2026-07-28 Tue] +:LAST_REVIEWED: 2026-07-28 +:END: +Neither surface that reports caffeine tells the truth reliably, so there is no way to know at a glance whether the screen will lock. Found while investigating the 2026-07-27 lockout, where Craig believed caffeine was on and the screen locked anyway. + +Defect 1 — the settings panel shows a frozen value. =gui.py= calls =_refresh_async()= once during window construction (line 454) and again only after the user's own actions (=_after_matrix=, line 663). The only two =GLib.timeout_add= calls are one-shots (the 2400ms toast hide and a 350ms fire), so nothing re-reads state on a timer. An open panel therefore displays the caffeine value from the moment it opened, forever. Any external flip -- the waybar click, Super+I, the =caffeine-toggle= script -- leaves it stale with no self-correction. The panel is the only surface in the repo carrying a caffeine control (=panel.py:25=); maint has none and does not embed these toggles, so this is the display Craig read. + +Defect 2 — there is no caffeine indicator on the bar at all. =custom/caffeine= appears in neither the stowed =hyprland/.config/waybar/config= nor the live generated =/run/user/1000/waybar/config=, and no =custom/caffeine= block is defined anywhere in the waybar config dir. The =waybar-caffeine= script exists, works, and has its own passing test suite, but nothing displays it. So the bar has never been a source of caffeine state, and the keybind and script have been signalling (=pkill -RTMIN+8 waybar=) a module that isn't there. + +(An earlier read of this task said the bar showed two near-identical glyphs. That was wrong: the module is absent, not merely unstyled. The script's class names are still backwards -- =active= when caffeine is OFF, =inhibited= when ON -- and neither class is styled, but both points are moot until the module is actually in the bar.) + +Grading: Major severity (the panel reports state wrongly while it is open, and the only other surface does not exist, so there is no reliable source for a setting Craig actively manages) x most-of-the-time (any external toggle while the panel is open; the bar never shows it) = P2 = [#B]. + +Fix all three. Wire =custom/caffeine= into the bar, rename its classes so they describe caffeine rather than idle, and style them from the existing palette. Give the panel's toggle row a re-read on a timer or on focus-in. Solo -- buildable and testable, and the direction is settled by the defects rather than a taste call, though the bar color is worth a glance from Craig once it renders. + +All three shipped as dotfiles =033076c=, pushed. =custom/caffeine= now sits in the bar between DND and settings on =interval: 2=; classes renamed =on=/=off= and both styled, caffeine-ON in the theme's gold =#dab53d=; the panel re-reads live state every 3s while visible. Verified live in the stowed config and the generated =/run/user/1000/waybar/config=. The full suite caught a theme-copy regression (=themes/dupre/waybar.css= out of sync with =waybar/style.css=) that the focused suites missed. +** DONE [#B] hyprlock still exits mid-lock; the watchdog relaunch is silent :bug:hyprland:dotfiles: +CLOSED: [2026-07-29 Wed] +:PROPERTIES: +:CREATED: [2026-07-28 Tue] +:LAST_REVIEWED: 2026-07-28 +:END: +Craig, 2026-07-28 ~15:00: saw the Hyprland lockdead/error text blurred *behind* a working lock screen; it vanished when he authenticated. + +That ordering is the diagnosis. hyprlock's blur samples what the compositor is currently rendering, so the compositor was already showing lockdead when the new hyprlock attached. Sequence: hyprlock exits non-zero (no coredump, so it exits rather than crashing), Hyprland renders lockdead because the client is gone while the session stays locked, =screen-lock='s watchdog relaunches within =LOCK_RELAUNCH_DELAY= (0.5s), and the new client draws over the lockdead frame and blurs it. + +*The recovery worked.* On 2026-07-27 this same hyprlock exit produced two contending clients and a session recoverable only from another console. It now self-heals in half a second, and the residue is cosmetic. Both the flock guard (dotfiles =ec18fd7=) and the watchdog did their jobs — verified in this session's compositor log, where all four lock events created exactly one =sessionLock= and one =sessionLockSurface= each, against two of each on 2026-07-27. + +Two things remain. + +*Why hyprlock exits.* The wrapper's header blames GPU-resource invalidation across a display power-cycle (hyprlock#953), which =amdgpu.runpm=0= targets — and that parameter is live as of the 2026-07-28 08:59 reboot, confirmed in =/proc/cmdline=. There is also no DPMS idle rule any more (=e900903=), so idling never power-cycles the display. Yet hyprlock still exited. Strongest untested candidate: a screen recording (=wf-recorder= into =~/sync/recordings/2026-07-28-12-53-57.mkv=, running 12:53 until Craig killed it) held screencopy sessions on DP-4 across the lock. The compositor log carries 2454 screenshare sessions and a =CScreencopyProtocol= bind in the window between the last two locks. A screencopy client churning dmabufs alongside hyprlock's own is a plausible way to invalidate them, and it was the one large new variable that day. + +*The relaunch is silent.* The watchdog loop re-runs hyprlock and logs nothing, so there is no record of how often this fires, when, or with what exit code — which is exactly why the frequency couldn't be established from the logs. Log the exit code and a timestamp on each relaunch. + +Grading: Major severity (the lock client dies mid-lock, and the pre-fix version of this wedged a session unrecoverably) x most users frequently (twice in three days, and this is a single-user machine, so every occurrence lands on the only user) = P2 = [#B]. Downgraded from the 2026-07-27 [#A] because the wedge is fixed and the failure now self-heals. + +An earlier draft of this grading said "some users sometimes", which the matrix maps to P3 = [#C], not the [#B] written beside it. The frequency row was the wrong input rather than the letter: on a one-user machine a fault hitting twice in three days is frequent, not occasional. Corrected the input per the rule that a disputed grade is fixed at its inputs. + +Solo for the instrumentation half only: adding the relaunch logging is buildable, testable against the existing =tests/screen-lock= suite, and needs no decision. Diagnosing the exit is not solo — it needs a reproduction, and the likely trigger is Craig recording his screen. + +Next step when picked up: land the relaunch logging first so the next occurrence produces evidence, then try to reproduce by locking with =wf-recorder= running. + +Superseded 2026-07-29 by =[#A] Night watch and the lock watchdog fight each other=. The logging landed (dotfiles =5bbe2c3=) and answered it within hours: three =rc=143= entries, SIGTERM, from =settings-watch= killing hyprlock by design. Nothing was crashing, so both the AMD-iGPU and the screen-recorder hypotheses in this task are wrong. Kept closed rather than deleted because the reasoning that led here is worth the record. -- cgit v1.2.3